InterpAsm-armv5te-vfp.S revision d88756df5b4dbc6fd450afd0019a5f64ebe4432d
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/*
25 * ARMv5 definitions and declarations.
26 */
27
28/*
29ARM EABI general notes:
30
31r0-r3 hold first 4 args to a method; they are not preserved across method calls
32r4-r8 are available for general use
33r9 is given special treatment in some situations, but not for us
34r10 (sl) seems to be generally available
35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
36r12 (ip) is scratch -- not preserved across method calls
37r13 (sp) should be managed carefully in case a signal arrives
38r14 (lr) must be preserved
39r15 (pc) can be tinkered with directly
40
41r0 holds returns of <= 4 bytes
42r0-r1 hold returns of 8 bytes, low word in r0
43
44Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
46s0-s15 (d0-d7, q0-a3) do not need to be.
47
48Stack is "full descending".  Only the arguments that don't fit in the first 4
49registers are placed on the stack.  "sp" points at the first stacked argument
50(i.e. the 5th arg).
51
52VFP: single-precision results in s0, double-precision results in d0.
53
54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5564-bit quantities (long long, double) must be 64-bit aligned.
56*/
57
58/*
59Mterp and ARM notes:
60
61The following registers have fixed assignments:
62
63  reg nick      purpose
64  r4  rPC       interpreted program counter, used for fetching instructions
65  r5  rFP       interpreted frame pointer, used for accessing locals and args
66  r6  rGLUE     MterpGlue pointer
67  r7  rINST     first 16-bit code unit of current instruction
68  r8  rIBASE    interpreted instruction base pointer, used for computed goto
69
70Macros are provided for common operations.  Each macro MUST emit only
71one instruction to make instruction-counting easier.  They MUST NOT alter
72unspecified registers or condition codes.
73*/
74
75/* single-purpose registers, given names for clarity */
76#define rPC     r4
77#define rFP     r5
78#define rGLUE   r6
79#define rINST   r7
80#define rIBASE  r8
81
82/* save/restore the PC and/or FP from the glue struct */
83#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
84#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
85#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
86#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
87#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
88#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
89
90/*
91 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
92 * be done *before* something calls dvmThrowException.
93 *
94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96 *
97 * It's okay to do this more than once.
98 */
99#define EXPORT_PC() \
100    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
101
102/*
103 * Given a frame pointer, find the stack save area.
104 *
105 * In C this is "((StackSaveArea*)(_fp) -1)".
106 */
107#define SAVEAREA_FROM_FP(_reg, _fpreg) \
108    sub     _reg, _fpreg, #sizeofStackSaveArea
109
110/*
111 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
112 */
113#define FETCH_INST()            ldrh    rINST, [rPC]
114
115/*
116 * Fetch the next instruction from the specified offset.  Advances rPC
117 * to point to the next instruction.  "_count" is in 16-bit code units.
118 *
119 * Because of the limited size of immediate constants on ARM, this is only
120 * suitable for small forward movements (i.e. don't try to implement "goto"
121 * with this).
122 *
123 * This must come AFTER anything that can throw an exception, or the
124 * exception catch may miss.  (This also implies that it must come after
125 * EXPORT_PC().)
126 */
127#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
128
129/*
130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
131 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132 */
133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
134        ldrh    _dreg, [_sreg, #(_count*2)]!
135
136/*
137 * Fetch the next instruction from an offset specified by _reg.  Updates
138 * rPC to point to the next instruction.  "_reg" must specify the distance
139 * in bytes, *not* 16-bit code units, and may be a signed value.
140 *
141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
142 * bits that hold the shift distance are used for the half/byte/sign flags.
143 * In some cases we can pre-double _reg for free, so we require a byte offset
144 * here.
145 */
146#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
147
148/*
149 * Fetch a half-word code unit from an offset past the current PC.  The
150 * "_count" value is in 16-bit code units.  Does not advance rPC.
151 *
152 * The "_S" variant works the same but treats the value as signed.
153 */
154#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
155#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
156
157/*
158 * Fetch one byte from an offset past the current PC.  Pass in the same
159 * "_count" as you would for FETCH, and an additional 0/1 indicating which
160 * byte of the halfword you want (lo/hi).
161 */
162#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
163
164/*
165 * Put the instruction's opcode field into the specified register.
166 */
167#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
168
169/*
170 * Put the prefetched instruction's opcode field into the specified register.
171 */
172#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
173
174/*
175 * Begin executing the opcode in _reg.  Because this only jumps within the
176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177 */
178#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
180#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
181
182/*
183 * Get/set the 32-bit value from a Dalvik register.
184 */
185#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
186#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
187
188#if defined(WITH_JIT)
189#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
191#endif
192
193/*
194 * Convert a virtual register index into an address.
195 */
196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
197        add     _reg, rFP, _vreg, lsl #2
198
199/*
200 * This is a #include, not a %include, because we want the C pre-processor
201 * to expand the macros into assembler assignment statements.
202 */
203#include "../common/asm-constants.h"
204
205#if defined(WITH_JIT)
206#include "../common/jit-config.h"
207#endif
208
209/* File: armv5te/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216/*
217 * Macro for data memory barrier; not meaningful pre-ARMv6K.
218 */
219.macro  SMP_DMB
220.endm
221
222/*
223 * Macro for data memory barrier; not meaningful pre-ARMv6K.
224 */
225.macro  SMP_DMB_ST
226.endm
227
228/* File: armv5te/entry.S */
229/*
230 * Copyright (C) 2008 The Android Open Source Project
231 *
232 * Licensed under the Apache License, Version 2.0 (the "License");
233 * you may not use this file except in compliance with the License.
234 * You may obtain a copy of the License at
235 *
236 *      http://www.apache.org/licenses/LICENSE-2.0
237 *
238 * Unless required by applicable law or agreed to in writing, software
239 * distributed under the License is distributed on an "AS IS" BASIS,
240 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241 * See the License for the specific language governing permissions and
242 * limitations under the License.
243 */
244/*
245 * Interpreter entry point.
246 */
247
248/*
249 * We don't have formal stack frames, so gdb scans upward in the code
250 * to find the start of the function (a label with the %function type),
251 * and then looks at the next few instructions to figure out what
252 * got pushed onto the stack.  From this it figures out how to restore
253 * the registers, including PC, for the previous stack frame.  If gdb
254 * sees a non-function label, it stops scanning, so either we need to
255 * have nothing but assembler-local labels between the entry point and
256 * the break, or we need to fake it out.
257 *
258 * When this is defined, we add some stuff to make gdb less confused.
259 */
260#define ASSIST_DEBUGGER 1
261
262    .text
263    .align  2
264    .global dvmMterpStdRun
265    .type   dvmMterpStdRun, %function
266
267/*
268 * On entry:
269 *  r0  MterpGlue* glue
270 *
271 * This function returns a boolean "changeInterp" value.  The return comes
272 * via a call to dvmMterpStdBail().
273 */
274dvmMterpStdRun:
275#define MTERP_ENTRY1 \
276    .save {r4-r10,fp,lr}; \
277    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
278#define MTERP_ENTRY2 \
279    .pad    #4; \
280    sub     sp, sp, #4                  @ align 64
281
282    .fnstart
283    MTERP_ENTRY1
284    MTERP_ENTRY2
285
286    /* save stack pointer, add magic word for debuggerd */
287    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
288
289    /* set up "named" registers, figure out entry point */
290    mov     rGLUE, r0                   @ set rGLUE
291    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
292    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
293    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
294    cmp     r1, #kInterpEntryInstr      @ usual case?
295    bne     .Lnot_instr                 @ no, handle it
296
297#if defined(WITH_JIT)
298.LentryInstr:
299    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
300    /* Entry is always a possible trace start */
301    GET_JIT_PROF_TABLE(r0)
302    FETCH_INST()
303    mov     r1, #0                      @ prepare the value for the new state
304    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
305    cmp     r0,#0                       @ is profiling disabled?
306#if !defined(WITH_SELF_VERIFICATION)
307    bne     common_updateProfile        @ profiling is enabled
308#else
309    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
310    beq     1f                          @ profiling is disabled
311    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
312    cmp     r3, #kSVSTraceSelect        @ hot trace following?
313    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
314    beq     common_selectTrace          @ go build the trace
315    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
316    beq     1f                          @ intrepret the next instruction
317    b       common_updateProfile        @ collect profiles
318#endif
3191:
320    GET_INST_OPCODE(ip)
321    GOTO_OPCODE(ip)
322#else
323    /* start executing the instruction at rPC */
324    FETCH_INST()                        @ load rINST from rPC
325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
326    GOTO_OPCODE(ip)                     @ jump to next instruction
327#endif
328
329.Lnot_instr:
330    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
331    beq     common_returnFromMethod
332
333.Lnot_return:
334    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
335    beq     common_exceptionThrown
336
337#if defined(WITH_JIT)
338.Lnot_throw:
339    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
340    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
341    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
342    bne     .Lbad_arg
343    cmp     rPC,r2
344    bne     .LentryInstr                @ must have branched, don't resume
345#if defined(WITH_SELF_VERIFICATION)
346    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
347    b       jitSVShadowRunStart         @ re-enter the translation after the
348                                        @ single-stepped instruction
349    @noreturn
350#endif
351    mov     r1, #kInterpEntryInstr
352    str     r1, [rGLUE, #offGlue_entryPoint]
353    bx      r10                         @ re-enter the translation
354#endif
355
356.Lbad_arg:
357    ldr     r0, strBadEntryPoint
358    @ r1 holds value of entryPoint
359    bl      printf
360    bl      dvmAbort
361    .fnend
362
363
364    .global dvmMterpStdBail
365    .type   dvmMterpStdBail, %function
366
367/*
368 * Restore the stack pointer and PC from the save point established on entry.
369 * This is essentially the same as a longjmp, but should be cheaper.  The
370 * last instruction causes us to return to whoever called dvmMterpStdRun.
371 *
372 * We pushed some registers on the stack in dvmMterpStdRun, then saved
373 * SP and LR.  Here we restore SP, restore the registers, and then restore
374 * LR to PC.
375 *
376 * On entry:
377 *  r0  MterpGlue* glue
378 *  r1  bool changeInterp
379 */
380dvmMterpStdBail:
381    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
382    mov     r0, r1                          @ return the changeInterp value
383    add     sp, sp, #4                      @ un-align 64
384    ldmfd   sp!, {r4-r10,fp,pc}             @ restore 9 regs and return
385
386
387/*
388 * String references.
389 */
390strBadEntryPoint:
391    .word   .LstrBadEntryPoint
392
393
394    .global dvmAsmInstructionStart
395    .type   dvmAsmInstructionStart, %function
396dvmAsmInstructionStart = .L_OP_NOP
397    .text
398
399/* ------------------------------ */
400    .balign 64
401.L_OP_NOP: /* 0x00 */
402/* File: armv5te/OP_NOP.S */
403    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
404    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
405    GOTO_OPCODE(ip)                     @ execute it
406
407#ifdef ASSIST_DEBUGGER
408    /* insert fake function header to help gdb find the stack frame */
409    .type   dalvik_inst, %function
410dalvik_inst:
411    .fnstart
412    MTERP_ENTRY1
413    MTERP_ENTRY2
414    .fnend
415#endif
416
417/* ------------------------------ */
418    .balign 64
419.L_OP_MOVE: /* 0x01 */
420/* File: armv5te/OP_MOVE.S */
421    /* for move, move-object, long-to-int */
422    /* op vA, vB */
423    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
424    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
425    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
426    GET_VREG(r2, r1)                    @ r2<- fp[B]
427    and     r0, r0, #15
428    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
429    SET_VREG(r2, r0)                    @ fp[A]<- r2
430    GOTO_OPCODE(ip)                     @ execute next instruction
431
432/* ------------------------------ */
433    .balign 64
434.L_OP_MOVE_FROM16: /* 0x02 */
435/* File: armv5te/OP_MOVE_FROM16.S */
436    /* for: move/from16, move-object/from16 */
437    /* op vAA, vBBBB */
438    FETCH(r1, 1)                        @ r1<- BBBB
439    mov     r0, rINST, lsr #8           @ r0<- AA
440    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
441    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
442    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
443    SET_VREG(r2, r0)                    @ fp[AA]<- r2
444    GOTO_OPCODE(ip)                     @ jump to next instruction
445
446/* ------------------------------ */
447    .balign 64
448.L_OP_MOVE_16: /* 0x03 */
449/* File: armv5te/OP_MOVE_16.S */
450    /* for: move/16, move-object/16 */
451    /* op vAAAA, vBBBB */
452    FETCH(r1, 2)                        @ r1<- BBBB
453    FETCH(r0, 1)                        @ r0<- AAAA
454    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
455    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
457    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
458    GOTO_OPCODE(ip)                     @ jump to next instruction
459
460/* ------------------------------ */
461    .balign 64
462.L_OP_MOVE_WIDE: /* 0x04 */
463/* File: armv5te/OP_MOVE_WIDE.S */
464    /* move-wide vA, vB */
465    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
466    mov     r2, rINST, lsr #8           @ r2<- A(+)
467    mov     r3, rINST, lsr #12          @ r3<- B
468    and     r2, r2, #15
469    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
470    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
471    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
472    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
473    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
474    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
475    GOTO_OPCODE(ip)                     @ jump to next instruction
476
477/* ------------------------------ */
478    .balign 64
479.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
480/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
481    /* move-wide/from16 vAA, vBBBB */
482    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
483    FETCH(r3, 1)                        @ r3<- BBBB
484    mov     r2, rINST, lsr #8           @ r2<- AA
485    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
486    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
487    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
488    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
489    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
490    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
491    GOTO_OPCODE(ip)                     @ jump to next instruction
492
493/* ------------------------------ */
494    .balign 64
495.L_OP_MOVE_WIDE_16: /* 0x06 */
496/* File: armv5te/OP_MOVE_WIDE_16.S */
497    /* move-wide/16 vAAAA, vBBBB */
498    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
499    FETCH(r3, 2)                        @ r3<- BBBB
500    FETCH(r2, 1)                        @ r2<- AAAA
501    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
502    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
503    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
504    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
506    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
507    GOTO_OPCODE(ip)                     @ jump to next instruction
508
509/* ------------------------------ */
510    .balign 64
511.L_OP_MOVE_OBJECT: /* 0x07 */
512/* File: armv5te/OP_MOVE_OBJECT.S */
513/* File: armv5te/OP_MOVE.S */
514    /* for move, move-object, long-to-int */
515    /* op vA, vB */
516    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
517    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
519    GET_VREG(r2, r1)                    @ r2<- fp[B]
520    and     r0, r0, #15
521    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
522    SET_VREG(r2, r0)                    @ fp[A]<- r2
523    GOTO_OPCODE(ip)                     @ execute next instruction
524
525
526/* ------------------------------ */
527    .balign 64
528.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
529/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
530/* File: armv5te/OP_MOVE_FROM16.S */
531    /* for: move/from16, move-object/from16 */
532    /* op vAA, vBBBB */
533    FETCH(r1, 1)                        @ r1<- BBBB
534    mov     r0, rINST, lsr #8           @ r0<- AA
535    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
536    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
538    SET_VREG(r2, r0)                    @ fp[AA]<- r2
539    GOTO_OPCODE(ip)                     @ jump to next instruction
540
541
542/* ------------------------------ */
543    .balign 64
544.L_OP_MOVE_OBJECT_16: /* 0x09 */
545/* File: armv5te/OP_MOVE_OBJECT_16.S */
546/* File: armv5te/OP_MOVE_16.S */
547    /* for: move/16, move-object/16 */
548    /* op vAAAA, vBBBB */
549    FETCH(r1, 2)                        @ r1<- BBBB
550    FETCH(r0, 1)                        @ r0<- AAAA
551    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
552    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
554    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
555    GOTO_OPCODE(ip)                     @ jump to next instruction
556
557
558/* ------------------------------ */
559    .balign 64
560.L_OP_MOVE_RESULT: /* 0x0a */
561/* File: armv5te/OP_MOVE_RESULT.S */
562    /* for: move-result, move-result-object */
563    /* op vAA */
564    mov     r2, rINST, lsr #8           @ r2<- AA
565    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
566    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
568    SET_VREG(r0, r2)                    @ fp[AA]<- r0
569    GOTO_OPCODE(ip)                     @ jump to next instruction
570
571/* ------------------------------ */
572    .balign 64
573.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
574/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
575    /* move-result-wide vAA */
576    mov     r2, rINST, lsr #8           @ r2<- AA
577    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
578    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
579    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
580    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
582    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
583    GOTO_OPCODE(ip)                     @ jump to next instruction
584
585/* ------------------------------ */
586    .balign 64
587.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
588/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
589/* File: armv5te/OP_MOVE_RESULT.S */
590    /* for: move-result, move-result-object */
591    /* op vAA */
592    mov     r2, rINST, lsr #8           @ r2<- AA
593    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
594    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596    SET_VREG(r0, r2)                    @ fp[AA]<- r0
597    GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600/* ------------------------------ */
601    .balign 64
602.L_OP_MOVE_EXCEPTION: /* 0x0d */
603/* File: armv5te/OP_MOVE_EXCEPTION.S */
604    /* move-exception vAA */
605    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
606    mov     r2, rINST, lsr #8           @ r2<- AA
607    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
608    mov     r1, #0                      @ r1<- 0
609    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
610    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
611    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
612    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
613    GOTO_OPCODE(ip)                     @ jump to next instruction
614
615/* ------------------------------ */
616    .balign 64
617.L_OP_RETURN_VOID: /* 0x0e */
618/* File: armv5te/OP_RETURN_VOID.S */
619    b       common_returnFromMethod
620
621/* ------------------------------ */
622    .balign 64
623.L_OP_RETURN: /* 0x0f */
624/* File: armv5te/OP_RETURN.S */
625    /*
626     * Return a 32-bit value.  Copies the return value into the "glue"
627     * structure, then jumps to the return handler.
628     *
629     * for: return, return-object
630     */
631    /* op vAA */
632    mov     r2, rINST, lsr #8           @ r2<- AA
633    GET_VREG(r0, r2)                    @ r0<- vAA
634    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
635    b       common_returnFromMethod
636
637/* ------------------------------ */
638    .balign 64
639.L_OP_RETURN_WIDE: /* 0x10 */
640/* File: armv5te/OP_RETURN_WIDE.S */
641    /*
642     * Return a 64-bit value.  Copies the return value into the "glue"
643     * structure, then jumps to the return handler.
644     */
645    /* return-wide vAA */
646    mov     r2, rINST, lsr #8           @ r2<- AA
647    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
648    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
649    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
650    stmia   r3, {r0-r1}                 @ retval<- r0/r1
651    b       common_returnFromMethod
652
653/* ------------------------------ */
654    .balign 64
655.L_OP_RETURN_OBJECT: /* 0x11 */
656/* File: armv5te/OP_RETURN_OBJECT.S */
657/* File: armv5te/OP_RETURN.S */
658    /*
659     * Return a 32-bit value.  Copies the return value into the "glue"
660     * structure, then jumps to the return handler.
661     *
662     * for: return, return-object
663     */
664    /* op vAA */
665    mov     r2, rINST, lsr #8           @ r2<- AA
666    GET_VREG(r0, r2)                    @ r0<- vAA
667    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
668    b       common_returnFromMethod
669
670
671/* ------------------------------ */
672    .balign 64
673.L_OP_CONST_4: /* 0x12 */
674/* File: armv5te/OP_CONST_4.S */
675    /* const/4 vA, #+B */
676    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
677    mov     r0, rINST, lsr #8           @ r0<- A+
678    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
679    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
680    and     r0, r0, #15
681    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
682    SET_VREG(r1, r0)                    @ fp[A]<- r1
683    GOTO_OPCODE(ip)                     @ execute next instruction
684
685/* ------------------------------ */
686    .balign 64
687.L_OP_CONST_16: /* 0x13 */
688/* File: armv5te/OP_CONST_16.S */
689    /* const/16 vAA, #+BBBB */
690    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
691    mov     r3, rINST, lsr #8           @ r3<- AA
692    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
693    SET_VREG(r0, r3)                    @ vAA<- r0
694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
695    GOTO_OPCODE(ip)                     @ jump to next instruction
696
697/* ------------------------------ */
698    .balign 64
699.L_OP_CONST: /* 0x14 */
700/* File: armv5te/OP_CONST.S */
701    /* const vAA, #+BBBBbbbb */
702    mov     r3, rINST, lsr #8           @ r3<- AA
703    FETCH(r0, 1)                        @ r0<- bbbb (low)
704    FETCH(r1, 2)                        @ r1<- BBBB (high)
705    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
706    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
708    SET_VREG(r0, r3)                    @ vAA<- r0
709    GOTO_OPCODE(ip)                     @ jump to next instruction
710
711/* ------------------------------ */
712    .balign 64
713.L_OP_CONST_HIGH16: /* 0x15 */
714/* File: armv5te/OP_CONST_HIGH16.S */
715    /* const/high16 vAA, #+BBBB0000 */
716    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
717    mov     r3, rINST, lsr #8           @ r3<- AA
718    mov     r0, r0, lsl #16             @ r0<- BBBB0000
719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
720    SET_VREG(r0, r3)                    @ vAA<- r0
721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
722    GOTO_OPCODE(ip)                     @ jump to next instruction
723
724/* ------------------------------ */
725    .balign 64
726.L_OP_CONST_WIDE_16: /* 0x16 */
727/* File: armv5te/OP_CONST_WIDE_16.S */
728    /* const-wide/16 vAA, #+BBBB */
729    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
730    mov     r3, rINST, lsr #8           @ r3<- AA
731    mov     r1, r0, asr #31             @ r1<- ssssssss
732    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
733    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
734    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
735    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
736    GOTO_OPCODE(ip)                     @ jump to next instruction
737
738/* ------------------------------ */
739    .balign 64
740.L_OP_CONST_WIDE_32: /* 0x17 */
741/* File: armv5te/OP_CONST_WIDE_32.S */
742    /* const-wide/32 vAA, #+BBBBbbbb */
743    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
744    mov     r3, rINST, lsr #8           @ r3<- AA
745    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
746    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
747    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
748    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
749    mov     r1, r0, asr #31             @ r1<- ssssssss
750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
751    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
752    GOTO_OPCODE(ip)                     @ jump to next instruction
753
754/* ------------------------------ */
755    .balign 64
756.L_OP_CONST_WIDE: /* 0x18 */
757/* File: armv5te/OP_CONST_WIDE.S */
758    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
759    FETCH(r0, 1)                        @ r0<- bbbb (low)
760    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
761    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
762    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
763    FETCH(r3, 4)                        @ r3<- HHHH (high)
764    mov     r9, rINST, lsr #8           @ r9<- AA
765    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
766    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
767    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
768    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
769    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
770    GOTO_OPCODE(ip)                     @ jump to next instruction
771
772/* ------------------------------ */
773    .balign 64
774.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
775/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
776    /* const-wide/high16 vAA, #+BBBB000000000000 */
777    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
778    mov     r3, rINST, lsr #8           @ r3<- AA
779    mov     r0, #0                      @ r0<- 00000000
780    mov     r1, r1, lsl #16             @ r1<- BBBB0000
781    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
782    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
783    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
784    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
785    GOTO_OPCODE(ip)                     @ jump to next instruction
786
787/* ------------------------------ */
788    .balign 64
789.L_OP_CONST_STRING: /* 0x1a */
790/* File: armv5te/OP_CONST_STRING.S */
791    /* const/string vAA, String@BBBB */
792    FETCH(r1, 1)                        @ r1<- BBBB
793    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
794    mov     r9, rINST, lsr #8           @ r9<- AA
795    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
796    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
797    cmp     r0, #0                      @ not yet resolved?
798    beq     .LOP_CONST_STRING_resolve
799    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
801    SET_VREG(r0, r9)                    @ vAA<- r0
802    GOTO_OPCODE(ip)                     @ jump to next instruction
803
804/* ------------------------------ */
805    .balign 64
806.L_OP_CONST_STRING_JUMBO: /* 0x1b */
807/* File: armv5te/OP_CONST_STRING_JUMBO.S */
808    /* const/string vAA, String@BBBBBBBB */
809    FETCH(r0, 1)                        @ r0<- bbbb (low)
810    FETCH(r1, 2)                        @ r1<- BBBB (high)
811    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
812    mov     r9, rINST, lsr #8           @ r9<- AA
813    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
814    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
815    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
816    cmp     r0, #0
817    beq     .LOP_CONST_STRING_JUMBO_resolve
818    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
819    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
820    SET_VREG(r0, r9)                    @ vAA<- r0
821    GOTO_OPCODE(ip)                     @ jump to next instruction
822
823/* ------------------------------ */
824    .balign 64
825.L_OP_CONST_CLASS: /* 0x1c */
826/* File: armv5te/OP_CONST_CLASS.S */
827    /* const/class vAA, Class@BBBB */
828    FETCH(r1, 1)                        @ r1<- BBBB
829    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
830    mov     r9, rINST, lsr #8           @ r9<- AA
831    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
832    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
833    cmp     r0, #0                      @ not yet resolved?
834    beq     .LOP_CONST_CLASS_resolve
835    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
837    SET_VREG(r0, r9)                    @ vAA<- r0
838    GOTO_OPCODE(ip)                     @ jump to next instruction
839
840/* ------------------------------ */
841    .balign 64
842.L_OP_MONITOR_ENTER: /* 0x1d */
843/* File: armv5te/OP_MONITOR_ENTER.S */
844    /*
845     * Synchronize on an object.
846     */
847    /* monitor-enter vAA */
848    mov     r2, rINST, lsr #8           @ r2<- AA
849    GET_VREG(r1, r2)                    @ r1<- vAA (object)
850    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
851    cmp     r1, #0                      @ null object?
852    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
853    beq     common_errNullObject        @ null object, throw an exception
854    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
855    bl      dvmLockObject               @ call(self, obj)
856#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
857    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
858    ldr     r1, [r0, #offThread_exception] @ check for exception
859    cmp     r1, #0
860    bne     common_exceptionThrown      @ exception raised, bail out
861#endif
862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
863    GOTO_OPCODE(ip)                     @ jump to next instruction
864
865/* ------------------------------ */
866    .balign 64
867.L_OP_MONITOR_EXIT: /* 0x1e */
868/* File: armv5te/OP_MONITOR_EXIT.S */
869    /*
870     * Unlock an object.
871     *
872     * Exceptions that occur when unlocking a monitor need to appear as
873     * if they happened at the following instruction.  See the Dalvik
874     * instruction spec.
875     */
876    /* monitor-exit vAA */
877    mov     r2, rINST, lsr #8           @ r2<- AA
878    EXPORT_PC()                         @ before fetch: export the PC
879    GET_VREG(r1, r2)                    @ r1<- vAA (object)
880    cmp     r1, #0                      @ null object?
881    beq     1f                          @ yes
882    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
883    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
884    cmp     r0, #0                      @ failed?
885    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
886    beq     common_exceptionThrown      @ yes, exception is pending
887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
888    GOTO_OPCODE(ip)                     @ jump to next instruction
8891:
890    FETCH_ADVANCE_INST(1)               @ advance before throw
891    b      common_errNullObject
892
893/* ------------------------------ */
894    .balign 64
895.L_OP_CHECK_CAST: /* 0x1f */
896/* File: armv5te/OP_CHECK_CAST.S */
897    /*
898     * Check to see if a cast from one class to another is allowed.
899     */
900    /* check-cast vAA, class@BBBB */
901    mov     r3, rINST, lsr #8           @ r3<- AA
902    FETCH(r2, 1)                        @ r2<- BBBB
903    GET_VREG(r9, r3)                    @ r9<- object
904    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
905    cmp     r9, #0                      @ is object null?
906    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
907    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
908    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
909    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
910    cmp     r1, #0                      @ have we resolved this before?
911    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
912.LOP_CHECK_CAST_resolved:
913    cmp     r0, r1                      @ same class (trivial success)?
914    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
915.LOP_CHECK_CAST_okay:
916    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918    GOTO_OPCODE(ip)                     @ jump to next instruction
919
920/* ------------------------------ */
921    .balign 64
922.L_OP_INSTANCE_OF: /* 0x20 */
923/* File: armv5te/OP_INSTANCE_OF.S */
924    /*
925     * Check to see if an object reference is an instance of a class.
926     *
927     * Most common situation is a non-null object, being compared against
928     * an already-resolved class.
929     */
930    /* instance-of vA, vB, class@CCCC */
931    mov     r3, rINST, lsr #12          @ r3<- B
932    mov     r9, rINST, lsr #8           @ r9<- A+
933    GET_VREG(r0, r3)                    @ r0<- vB (object)
934    and     r9, r9, #15                 @ r9<- A
935    cmp     r0, #0                      @ is object null?
936    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
937    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
938    FETCH(r3, 1)                        @ r3<- CCCC
939    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
940    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
941    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
942    cmp     r1, #0                      @ have we resolved this before?
943    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
944.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
945    cmp     r0, r1                      @ same class (trivial success)?
946    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
947    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
948
949/* ------------------------------ */
950    .balign 64
951.L_OP_ARRAY_LENGTH: /* 0x21 */
952/* File: armv5te/OP_ARRAY_LENGTH.S */
953    /*
954     * Return the length of an array.
955     */
956    mov     r1, rINST, lsr #12          @ r1<- B
957    mov     r2, rINST, lsr #8           @ r2<- A+
958    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
959    and     r2, r2, #15                 @ r2<- A
960    cmp     r0, #0                      @ is object null?
961    beq     common_errNullObject        @ yup, fail
962    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
963    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
964    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
965    SET_VREG(r3, r2)                    @ vB<- length
966    GOTO_OPCODE(ip)                     @ jump to next instruction
967
968/* ------------------------------ */
969    .balign 64
970.L_OP_NEW_INSTANCE: /* 0x22 */
971/* File: armv5te/OP_NEW_INSTANCE.S */
972    /*
973     * Create a new instance of a class.
974     */
975    /* new-instance vAA, class@BBBB */
976    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
977    FETCH(r1, 1)                        @ r1<- BBBB
978    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
979    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
980    EXPORT_PC()                         @ req'd for init, resolve, alloc
981    cmp     r0, #0                      @ already resolved?
982    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
983.LOP_NEW_INSTANCE_resolved:   @ r0=class
984    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
985    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
986    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
987.LOP_NEW_INSTANCE_initialized: @ r0=class
988    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
989    bl      dvmAllocObject              @ r0<- new object
990    b       .LOP_NEW_INSTANCE_finish          @ continue
991
992/* ------------------------------ */
993    .balign 64
994.L_OP_NEW_ARRAY: /* 0x23 */
995/* File: armv5te/OP_NEW_ARRAY.S */
996    /*
997     * Allocate an array of objects, specified with the array class
998     * and a count.
999     *
1000     * The verifier guarantees that this is an array class, so we don't
1001     * check for it here.
1002     */
1003    /* new-array vA, vB, class@CCCC */
1004    mov     r0, rINST, lsr #12          @ r0<- B
1005    FETCH(r2, 1)                        @ r2<- CCCC
1006    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1007    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1008    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1009    cmp     r1, #0                      @ check length
1010    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1011    bmi     common_errNegativeArraySize @ negative length, bail
1012    cmp     r0, #0                      @ already resolved?
1013    EXPORT_PC()                         @ req'd for resolve, alloc
1014    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1015    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1016
1017/* ------------------------------ */
1018    .balign 64
1019.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1020/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1021    /*
1022     * Create a new array with elements filled from registers.
1023     *
1024     * for: filled-new-array, filled-new-array/range
1025     */
1026    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1027    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1028    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1029    FETCH(r1, 1)                        @ r1<- BBBB
1030    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1031    EXPORT_PC()                         @ need for resolve and alloc
1032    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1033    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1034    cmp     r0, #0                      @ already resolved?
1035    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10368:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1037    mov     r2, #0                      @ r2<- false
1038    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1039    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1040    cmp     r0, #0                      @ got null?
1041    beq     common_exceptionThrown      @ yes, handle exception
1042    b       .LOP_FILLED_NEW_ARRAY_continue
1043
1044/* ------------------------------ */
1045    .balign 64
1046.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1047/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1048/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1049    /*
1050     * Create a new array with elements filled from registers.
1051     *
1052     * for: filled-new-array, filled-new-array/range
1053     */
1054    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1055    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1056    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1057    FETCH(r1, 1)                        @ r1<- BBBB
1058    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1059    EXPORT_PC()                         @ need for resolve and alloc
1060    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1061    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1062    cmp     r0, #0                      @ already resolved?
1063    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10648:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1065    mov     r2, #0                      @ r2<- false
1066    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1067    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1068    cmp     r0, #0                      @ got null?
1069    beq     common_exceptionThrown      @ yes, handle exception
1070    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1071
1072
1073/* ------------------------------ */
1074    .balign 64
1075.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1076/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1077    /* fill-array-data vAA, +BBBBBBBB */
1078    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1079    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1080    mov     r3, rINST, lsr #8           @ r3<- AA
1081    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1082    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1083    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1084    EXPORT_PC();
1085    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1086    cmp     r0, #0                      @ 0 means an exception is thrown
1087    beq     common_exceptionThrown      @ has exception
1088    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1089    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1090    GOTO_OPCODE(ip)                     @ jump to next instruction
1091
1092/* ------------------------------ */
1093    .balign 64
1094.L_OP_THROW: /* 0x27 */
1095/* File: armv5te/OP_THROW.S */
1096    /*
1097     * Throw an exception object in the current thread.
1098     */
1099    /* throw vAA */
1100    mov     r2, rINST, lsr #8           @ r2<- AA
1101    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1102    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1103    EXPORT_PC()                         @ exception handler can throw
1104    cmp     r1, #0                      @ null object?
1105    beq     common_errNullObject        @ yes, throw an NPE instead
1106    @ bypass dvmSetException, just store it
1107    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1108    b       common_exceptionThrown
1109
1110/* ------------------------------ */
1111    .balign 64
1112.L_OP_GOTO: /* 0x28 */
1113/* File: armv5te/OP_GOTO.S */
1114    /*
1115     * Unconditional branch, 8-bit offset.
1116     *
1117     * The branch distance is a signed code-unit offset, which we need to
1118     * double to get a byte offset.
1119     */
1120    /* goto +AA */
1121    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1122    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1123    mov     r9, r9, lsl #1              @ r9<- byte offset
1124    bmi     common_backwardBranch       @ backward branch, do periodic checks
1125#if defined(WITH_JIT)
1126    GET_JIT_PROF_TABLE(r0)
1127    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1128    cmp     r0,#0
1129    bne     common_updateProfile
1130    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1131    GOTO_OPCODE(ip)                     @ jump to next instruction
1132#else
1133    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1134    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1135    GOTO_OPCODE(ip)                     @ jump to next instruction
1136#endif
1137
1138/* ------------------------------ */
1139    .balign 64
1140.L_OP_GOTO_16: /* 0x29 */
1141/* File: armv5te/OP_GOTO_16.S */
1142    /*
1143     * Unconditional branch, 16-bit offset.
1144     *
1145     * The branch distance is a signed code-unit offset, which we need to
1146     * double to get a byte offset.
1147     */
1148    /* goto/16 +AAAA */
1149    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1150    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1151    bmi     common_backwardBranch       @ backward branch, do periodic checks
1152#if defined(WITH_JIT)
1153    GET_JIT_PROF_TABLE(r0)
1154    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1155    cmp     r0,#0
1156    bne     common_updateProfile
1157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1158    GOTO_OPCODE(ip)                     @ jump to next instruction
1159#else
1160    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1162    GOTO_OPCODE(ip)                     @ jump to next instruction
1163#endif
1164
1165/* ------------------------------ */
1166    .balign 64
1167.L_OP_GOTO_32: /* 0x2a */
1168/* File: armv5te/OP_GOTO_32.S */
1169    /*
1170     * Unconditional branch, 32-bit offset.
1171     *
1172     * The branch distance is a signed code-unit offset, which we need to
1173     * double to get a byte offset.
1174     *
1175     * Unlike most opcodes, this one is allowed to branch to itself, so
1176     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1177     * instruction doesn't affect the V flag, so we need to clear it
1178     * explicitly.
1179     */
1180    /* goto/32 +AAAAAAAA */
1181    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1182    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1183    cmp     ip, ip                      @ (clear V flag during stall)
1184    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1185    mov     r9, r0, asl #1              @ r9<- byte offset
1186    ble     common_backwardBranch       @ backward branch, do periodic checks
1187#if defined(WITH_JIT)
1188    GET_JIT_PROF_TABLE(r0)
1189    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1190    cmp     r0,#0
1191    bne     common_updateProfile
1192    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1193    GOTO_OPCODE(ip)                     @ jump to next instruction
1194#else
1195    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1196    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1197    GOTO_OPCODE(ip)                     @ jump to next instruction
1198#endif
1199
1200/* ------------------------------ */
1201    .balign 64
1202.L_OP_PACKED_SWITCH: /* 0x2b */
1203/* File: armv5te/OP_PACKED_SWITCH.S */
1204    /*
1205     * Handle a packed-switch or sparse-switch instruction.  In both cases
1206     * we decode it and hand it off to a helper function.
1207     *
1208     * We don't really expect backward branches in a switch statement, but
1209     * they're perfectly legal, so we check for them here.
1210     *
1211     * for: packed-switch, sparse-switch
1212     */
1213    /* op vAA, +BBBB */
1214    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1215    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1216    mov     r3, rINST, lsr #8           @ r3<- AA
1217    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1218    GET_VREG(r1, r3)                    @ r1<- vAA
1219    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1220    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1221    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1222    bmi     common_backwardBranch       @ backward branch, do periodic checks
1223    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1224#if defined(WITH_JIT)
1225    GET_JIT_PROF_TABLE(r0)
1226    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1227    cmp     r0,#0
1228    bne     common_updateProfile
1229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1230    GOTO_OPCODE(ip)                     @ jump to next instruction
1231#else
1232    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1234    GOTO_OPCODE(ip)                     @ jump to next instruction
1235#endif
1236
1237/* ------------------------------ */
1238    .balign 64
1239.L_OP_SPARSE_SWITCH: /* 0x2c */
1240/* File: armv5te/OP_SPARSE_SWITCH.S */
1241/* File: armv5te/OP_PACKED_SWITCH.S */
1242    /*
1243     * Handle a packed-switch or sparse-switch instruction.  In both cases
1244     * we decode it and hand it off to a helper function.
1245     *
1246     * We don't really expect backward branches in a switch statement, but
1247     * they're perfectly legal, so we check for them here.
1248     *
1249     * for: packed-switch, sparse-switch
1250     */
1251    /* op vAA, +BBBB */
1252    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1253    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1254    mov     r3, rINST, lsr #8           @ r3<- AA
1255    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1256    GET_VREG(r1, r3)                    @ r1<- vAA
1257    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1258    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1259    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1260    bmi     common_backwardBranch       @ backward branch, do periodic checks
1261    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1262#if defined(WITH_JIT)
1263    GET_JIT_PROF_TABLE(r0)
1264    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1265    cmp     r0,#0
1266    bne     common_updateProfile
1267    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1268    GOTO_OPCODE(ip)                     @ jump to next instruction
1269#else
1270    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1271    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1272    GOTO_OPCODE(ip)                     @ jump to next instruction
1273#endif
1274
1275
1276/* ------------------------------ */
1277    .balign 64
1278.L_OP_CMPL_FLOAT: /* 0x2d */
1279/* File: arm-vfp/OP_CMPL_FLOAT.S */
1280    /*
1281     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1282     * destination register based on the results of the comparison.
1283     *
1284     * int compare(x, y) {
1285     *     if (x == y) {
1286     *         return 0;
1287     *     } else if (x > y) {
1288     *         return 1;
1289     *     } else if (x < y) {
1290     *         return -1;
1291     *     } else {
1292     *         return -1;
1293     *     }
1294     * }
1295     */
1296    /* op vAA, vBB, vCC */
1297    FETCH(r0, 1)                        @ r0<- CCBB
1298    mov     r9, rINST, lsr #8           @ r9<- AA
1299    and     r2, r0, #255                @ r2<- BB
1300    mov     r3, r0, lsr #8              @ r3<- CC
1301    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1302    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1303    flds    s0, [r2]                    @ s0<- vBB
1304    flds    s1, [r3]                    @ s1<- vCC
1305    fcmpes  s0, s1                      @ compare (vBB, vCC)
1306    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1307    mvn     r0, #0                      @ r0<- -1 (default)
1308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1309    fmstat                              @ export status flags
1310    movgt   r0, #1                      @ (greater than) r1<- 1
1311    moveq   r0, #0                      @ (equal) r1<- 0
1312    b       .LOP_CMPL_FLOAT_finish          @ argh
1313
1314
1315/* ------------------------------ */
1316    .balign 64
1317.L_OP_CMPG_FLOAT: /* 0x2e */
1318/* File: arm-vfp/OP_CMPG_FLOAT.S */
1319    /*
1320     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1321     * destination register based on the results of the comparison.
1322     *
1323     * int compare(x, y) {
1324     *     if (x == y) {
1325     *         return 0;
1326     *     } else if (x < y) {
1327     *         return -1;
1328     *     } else if (x > y) {
1329     *         return 1;
1330     *     } else {
1331     *         return 1;
1332     *     }
1333     * }
1334     */
1335    /* op vAA, vBB, vCC */
1336    FETCH(r0, 1)                        @ r0<- CCBB
1337    mov     r9, rINST, lsr #8           @ r9<- AA
1338    and     r2, r0, #255                @ r2<- BB
1339    mov     r3, r0, lsr #8              @ r3<- CC
1340    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1341    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1342    flds    s0, [r2]                    @ s0<- vBB
1343    flds    s1, [r3]                    @ s1<- vCC
1344    fcmpes  s0, s1                      @ compare (vBB, vCC)
1345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1346    mov     r0, #1                      @ r0<- 1 (default)
1347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1348    fmstat                              @ export status flags
1349    mvnmi   r0, #0                      @ (less than) r1<- -1
1350    moveq   r0, #0                      @ (equal) r1<- 0
1351    b       .LOP_CMPG_FLOAT_finish          @ argh
1352
1353
1354/* ------------------------------ */
1355    .balign 64
1356.L_OP_CMPL_DOUBLE: /* 0x2f */
1357/* File: arm-vfp/OP_CMPL_DOUBLE.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     * int compare(x, y) {
1363     *     if (x == y) {
1364     *         return 0;
1365     *     } else if (x > y) {
1366     *         return 1;
1367     *     } else if (x < y) {
1368     *         return -1;
1369     *     } else {
1370     *         return -1;
1371     *     }
1372     * }
1373     */
1374    /* op vAA, vBB, vCC */
1375    FETCH(r0, 1)                        @ r0<- CCBB
1376    mov     r9, rINST, lsr #8           @ r9<- AA
1377    and     r2, r0, #255                @ r2<- BB
1378    mov     r3, r0, lsr #8              @ r3<- CC
1379    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1380    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1381    fldd    d0, [r2]                    @ d0<- vBB
1382    fldd    d1, [r3]                    @ d1<- vCC
1383    fcmped  d0, d1                      @ compare (vBB, vCC)
1384    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1385    mvn     r0, #0                      @ r0<- -1 (default)
1386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1387    fmstat                              @ export status flags
1388    movgt   r0, #1                      @ (greater than) r1<- 1
1389    moveq   r0, #0                      @ (equal) r1<- 0
1390    b       .LOP_CMPL_DOUBLE_finish          @ argh
1391
1392
1393/* ------------------------------ */
1394    .balign 64
1395.L_OP_CMPG_DOUBLE: /* 0x30 */
1396/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1397    /*
1398     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1399     * destination register based on the results of the comparison.
1400     *
1401     * int compare(x, y) {
1402     *     if (x == y) {
1403     *         return 0;
1404     *     } else if (x < y) {
1405     *         return -1;
1406     *     } else if (x > y) {
1407     *         return 1;
1408     *     } else {
1409     *         return 1;
1410     *     }
1411     * }
1412     */
1413    /* op vAA, vBB, vCC */
1414    FETCH(r0, 1)                        @ r0<- CCBB
1415    mov     r9, rINST, lsr #8           @ r9<- AA
1416    and     r2, r0, #255                @ r2<- BB
1417    mov     r3, r0, lsr #8              @ r3<- CC
1418    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1419    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1420    fldd    d0, [r2]                    @ d0<- vBB
1421    fldd    d1, [r3]                    @ d1<- vCC
1422    fcmped  d0, d1                      @ compare (vBB, vCC)
1423    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1424    mov     r0, #1                      @ r0<- 1 (default)
1425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1426    fmstat                              @ export status flags
1427    mvnmi   r0, #0                      @ (less than) r1<- -1
1428    moveq   r0, #0                      @ (equal) r1<- 0
1429    b       .LOP_CMPG_DOUBLE_finish          @ argh
1430
1431
1432/* ------------------------------ */
1433    .balign 64
1434.L_OP_CMP_LONG: /* 0x31 */
1435/* File: armv5te/OP_CMP_LONG.S */
1436    /*
1437     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1438     * register based on the results of the comparison.
1439     *
1440     * We load the full values with LDM, but in practice many values could
1441     * be resolved by only looking at the high word.  This could be made
1442     * faster or slower by splitting the LDM into a pair of LDRs.
1443     *
1444     * If we just wanted to set condition flags, we could do this:
1445     *  subs    ip, r0, r2
1446     *  sbcs    ip, r1, r3
1447     *  subeqs  ip, r0, r2
1448     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1449     * integer value, which we can do with 2 conditional mov/mvn instructions
1450     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1451     * us a constant 5-cycle path plus a branch at the end to the
1452     * instruction epilogue code.  The multi-compare approach below needs
1453     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1454     * in the worst case (the 64-bit values are equal).
1455     */
1456    /* cmp-long vAA, vBB, vCC */
1457    FETCH(r0, 1)                        @ r0<- CCBB
1458    mov     r9, rINST, lsr #8           @ r9<- AA
1459    and     r2, r0, #255                @ r2<- BB
1460    mov     r3, r0, lsr #8              @ r3<- CC
1461    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1462    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1463    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1464    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1465    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1466    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1467    bgt     .LOP_CMP_LONG_greater
1468    subs    r1, r0, r2                  @ r1<- r0 - r2
1469    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1470    bne     .LOP_CMP_LONG_less
1471    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1472
1473/* ------------------------------ */
1474    .balign 64
1475.L_OP_IF_EQ: /* 0x32 */
1476/* File: armv5te/OP_IF_EQ.S */
1477/* File: armv5te/bincmp.S */
1478    /*
1479     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1480     * fragment that specifies the *reverse* comparison to perform, e.g.
1481     * for "if-le" you would use "gt".
1482     *
1483     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1484     */
1485    /* if-cmp vA, vB, +CCCC */
1486    mov     r0, rINST, lsr #8           @ r0<- A+
1487    mov     r1, rINST, lsr #12          @ r1<- B
1488    and     r0, r0, #15
1489    GET_VREG(r3, r1)                    @ r3<- vB
1490    GET_VREG(r2, r0)                    @ r2<- vA
1491    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1492    cmp     r2, r3                      @ compare (vA, vB)
1493    bne  1f                      @ branch to 1 if comparison failed
1494    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1495    movs    r9, r9, asl #1              @ convert to bytes, check sign
1496    bmi     common_backwardBranch       @ yes, do periodic checks
14971:
1498#if defined(WITH_JIT)
1499    GET_JIT_PROF_TABLE(r0)
1500    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1501    b        common_testUpdateProfile
1502#else
1503    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1504    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1505    GOTO_OPCODE(ip)                     @ jump to next instruction
1506#endif
1507
1508
1509/* ------------------------------ */
1510    .balign 64
1511.L_OP_IF_NE: /* 0x33 */
1512/* File: armv5te/OP_IF_NE.S */
1513/* File: armv5te/bincmp.S */
1514    /*
1515     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1516     * fragment that specifies the *reverse* comparison to perform, e.g.
1517     * for "if-le" you would use "gt".
1518     *
1519     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1520     */
1521    /* if-cmp vA, vB, +CCCC */
1522    mov     r0, rINST, lsr #8           @ r0<- A+
1523    mov     r1, rINST, lsr #12          @ r1<- B
1524    and     r0, r0, #15
1525    GET_VREG(r3, r1)                    @ r3<- vB
1526    GET_VREG(r2, r0)                    @ r2<- vA
1527    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1528    cmp     r2, r3                      @ compare (vA, vB)
1529    beq  1f                      @ branch to 1 if comparison failed
1530    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1531    movs    r9, r9, asl #1              @ convert to bytes, check sign
1532    bmi     common_backwardBranch       @ yes, do periodic checks
15331:
1534#if defined(WITH_JIT)
1535    GET_JIT_PROF_TABLE(r0)
1536    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1537    b        common_testUpdateProfile
1538#else
1539    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1541    GOTO_OPCODE(ip)                     @ jump to next instruction
1542#endif
1543
1544
1545/* ------------------------------ */
1546    .balign 64
1547.L_OP_IF_LT: /* 0x34 */
1548/* File: armv5te/OP_IF_LT.S */
1549/* File: armv5te/bincmp.S */
1550    /*
1551     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1552     * fragment that specifies the *reverse* comparison to perform, e.g.
1553     * for "if-le" you would use "gt".
1554     *
1555     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1556     */
1557    /* if-cmp vA, vB, +CCCC */
1558    mov     r0, rINST, lsr #8           @ r0<- A+
1559    mov     r1, rINST, lsr #12          @ r1<- B
1560    and     r0, r0, #15
1561    GET_VREG(r3, r1)                    @ r3<- vB
1562    GET_VREG(r2, r0)                    @ r2<- vA
1563    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1564    cmp     r2, r3                      @ compare (vA, vB)
1565    bge  1f                      @ branch to 1 if comparison failed
1566    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1567    movs    r9, r9, asl #1              @ convert to bytes, check sign
1568    bmi     common_backwardBranch       @ yes, do periodic checks
15691:
1570#if defined(WITH_JIT)
1571    GET_JIT_PROF_TABLE(r0)
1572    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1573    b        common_testUpdateProfile
1574#else
1575    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1577    GOTO_OPCODE(ip)                     @ jump to next instruction
1578#endif
1579
1580
1581/* ------------------------------ */
1582    .balign 64
1583.L_OP_IF_GE: /* 0x35 */
1584/* File: armv5te/OP_IF_GE.S */
1585/* File: armv5te/bincmp.S */
1586    /*
1587     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1588     * fragment that specifies the *reverse* comparison to perform, e.g.
1589     * for "if-le" you would use "gt".
1590     *
1591     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1592     */
1593    /* if-cmp vA, vB, +CCCC */
1594    mov     r0, rINST, lsr #8           @ r0<- A+
1595    mov     r1, rINST, lsr #12          @ r1<- B
1596    and     r0, r0, #15
1597    GET_VREG(r3, r1)                    @ r3<- vB
1598    GET_VREG(r2, r0)                    @ r2<- vA
1599    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1600    cmp     r2, r3                      @ compare (vA, vB)
1601    blt  1f                      @ branch to 1 if comparison failed
1602    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1603    movs    r9, r9, asl #1              @ convert to bytes, check sign
1604    bmi     common_backwardBranch       @ yes, do periodic checks
16051:
1606#if defined(WITH_JIT)
1607    GET_JIT_PROF_TABLE(r0)
1608    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1609    b        common_testUpdateProfile
1610#else
1611    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1612    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1613    GOTO_OPCODE(ip)                     @ jump to next instruction
1614#endif
1615
1616
1617/* ------------------------------ */
1618    .balign 64
1619.L_OP_IF_GT: /* 0x36 */
1620/* File: armv5te/OP_IF_GT.S */
1621/* File: armv5te/bincmp.S */
1622    /*
1623     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1624     * fragment that specifies the *reverse* comparison to perform, e.g.
1625     * for "if-le" you would use "gt".
1626     *
1627     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1628     */
1629    /* if-cmp vA, vB, +CCCC */
1630    mov     r0, rINST, lsr #8           @ r0<- A+
1631    mov     r1, rINST, lsr #12          @ r1<- B
1632    and     r0, r0, #15
1633    GET_VREG(r3, r1)                    @ r3<- vB
1634    GET_VREG(r2, r0)                    @ r2<- vA
1635    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1636    cmp     r2, r3                      @ compare (vA, vB)
1637    ble  1f                      @ branch to 1 if comparison failed
1638    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1639    movs    r9, r9, asl #1              @ convert to bytes, check sign
1640    bmi     common_backwardBranch       @ yes, do periodic checks
16411:
1642#if defined(WITH_JIT)
1643    GET_JIT_PROF_TABLE(r0)
1644    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1645    b        common_testUpdateProfile
1646#else
1647    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1648    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1649    GOTO_OPCODE(ip)                     @ jump to next instruction
1650#endif
1651
1652
1653/* ------------------------------ */
1654    .balign 64
1655.L_OP_IF_LE: /* 0x37 */
1656/* File: armv5te/OP_IF_LE.S */
1657/* File: armv5te/bincmp.S */
1658    /*
1659     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1660     * fragment that specifies the *reverse* comparison to perform, e.g.
1661     * for "if-le" you would use "gt".
1662     *
1663     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1664     */
1665    /* if-cmp vA, vB, +CCCC */
1666    mov     r0, rINST, lsr #8           @ r0<- A+
1667    mov     r1, rINST, lsr #12          @ r1<- B
1668    and     r0, r0, #15
1669    GET_VREG(r3, r1)                    @ r3<- vB
1670    GET_VREG(r2, r0)                    @ r2<- vA
1671    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1672    cmp     r2, r3                      @ compare (vA, vB)
1673    bgt  1f                      @ branch to 1 if comparison failed
1674    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1675    movs    r9, r9, asl #1              @ convert to bytes, check sign
1676    bmi     common_backwardBranch       @ yes, do periodic checks
16771:
1678#if defined(WITH_JIT)
1679    GET_JIT_PROF_TABLE(r0)
1680    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1681    b        common_testUpdateProfile
1682#else
1683    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1685    GOTO_OPCODE(ip)                     @ jump to next instruction
1686#endif
1687
1688
1689/* ------------------------------ */
1690    .balign 64
1691.L_OP_IF_EQZ: /* 0x38 */
1692/* File: armv5te/OP_IF_EQZ.S */
1693/* File: armv5te/zcmp.S */
1694    /*
1695     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1696     * fragment that specifies the *reverse* comparison to perform, e.g.
1697     * for "if-le" you would use "gt".
1698     *
1699     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1700     */
1701    /* if-cmp vAA, +BBBB */
1702    mov     r0, rINST, lsr #8           @ r0<- AA
1703    GET_VREG(r2, r0)                    @ r2<- vAA
1704    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1705    cmp     r2, #0                      @ compare (vA, 0)
1706    bne  1f                      @ branch to 1 if comparison failed
1707    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1708    movs    r9, r9, asl #1              @ convert to bytes, check sign
1709    bmi     common_backwardBranch       @ backward branch, do periodic checks
17101:
1711#if defined(WITH_JIT)
1712    GET_JIT_PROF_TABLE(r0)
1713    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1714    cmp     r0,#0
1715    bne     common_updateProfile
1716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1717    GOTO_OPCODE(ip)                     @ jump to next instruction
1718#else
1719    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1721    GOTO_OPCODE(ip)                     @ jump to next instruction
1722#endif
1723
1724
1725/* ------------------------------ */
1726    .balign 64
1727.L_OP_IF_NEZ: /* 0x39 */
1728/* File: armv5te/OP_IF_NEZ.S */
1729/* File: armv5te/zcmp.S */
1730    /*
1731     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1732     * fragment that specifies the *reverse* comparison to perform, e.g.
1733     * for "if-le" you would use "gt".
1734     *
1735     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1736     */
1737    /* if-cmp vAA, +BBBB */
1738    mov     r0, rINST, lsr #8           @ r0<- AA
1739    GET_VREG(r2, r0)                    @ r2<- vAA
1740    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1741    cmp     r2, #0                      @ compare (vA, 0)
1742    beq  1f                      @ branch to 1 if comparison failed
1743    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1744    movs    r9, r9, asl #1              @ convert to bytes, check sign
1745    bmi     common_backwardBranch       @ backward branch, do periodic checks
17461:
1747#if defined(WITH_JIT)
1748    GET_JIT_PROF_TABLE(r0)
1749    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1750    cmp     r0,#0
1751    bne     common_updateProfile
1752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1753    GOTO_OPCODE(ip)                     @ jump to next instruction
1754#else
1755    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1757    GOTO_OPCODE(ip)                     @ jump to next instruction
1758#endif
1759
1760
1761/* ------------------------------ */
1762    .balign 64
1763.L_OP_IF_LTZ: /* 0x3a */
1764/* File: armv5te/OP_IF_LTZ.S */
1765/* File: armv5te/zcmp.S */
1766    /*
1767     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1768     * fragment that specifies the *reverse* comparison to perform, e.g.
1769     * for "if-le" you would use "gt".
1770     *
1771     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1772     */
1773    /* if-cmp vAA, +BBBB */
1774    mov     r0, rINST, lsr #8           @ r0<- AA
1775    GET_VREG(r2, r0)                    @ r2<- vAA
1776    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1777    cmp     r2, #0                      @ compare (vA, 0)
1778    bge  1f                      @ branch to 1 if comparison failed
1779    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1780    movs    r9, r9, asl #1              @ convert to bytes, check sign
1781    bmi     common_backwardBranch       @ backward branch, do periodic checks
17821:
1783#if defined(WITH_JIT)
1784    GET_JIT_PROF_TABLE(r0)
1785    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1786    cmp     r0,#0
1787    bne     common_updateProfile
1788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1789    GOTO_OPCODE(ip)                     @ jump to next instruction
1790#else
1791    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1793    GOTO_OPCODE(ip)                     @ jump to next instruction
1794#endif
1795
1796
1797/* ------------------------------ */
1798    .balign 64
1799.L_OP_IF_GEZ: /* 0x3b */
1800/* File: armv5te/OP_IF_GEZ.S */
1801/* File: armv5te/zcmp.S */
1802    /*
1803     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1804     * fragment that specifies the *reverse* comparison to perform, e.g.
1805     * for "if-le" you would use "gt".
1806     *
1807     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1808     */
1809    /* if-cmp vAA, +BBBB */
1810    mov     r0, rINST, lsr #8           @ r0<- AA
1811    GET_VREG(r2, r0)                    @ r2<- vAA
1812    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1813    cmp     r2, #0                      @ compare (vA, 0)
1814    blt  1f                      @ branch to 1 if comparison failed
1815    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1816    movs    r9, r9, asl #1              @ convert to bytes, check sign
1817    bmi     common_backwardBranch       @ backward branch, do periodic checks
18181:
1819#if defined(WITH_JIT)
1820    GET_JIT_PROF_TABLE(r0)
1821    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1822    cmp     r0,#0
1823    bne     common_updateProfile
1824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1825    GOTO_OPCODE(ip)                     @ jump to next instruction
1826#else
1827    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829    GOTO_OPCODE(ip)                     @ jump to next instruction
1830#endif
1831
1832
1833/* ------------------------------ */
1834    .balign 64
1835.L_OP_IF_GTZ: /* 0x3c */
1836/* File: armv5te/OP_IF_GTZ.S */
1837/* File: armv5te/zcmp.S */
1838    /*
1839     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1840     * fragment that specifies the *reverse* comparison to perform, e.g.
1841     * for "if-le" you would use "gt".
1842     *
1843     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1844     */
1845    /* if-cmp vAA, +BBBB */
1846    mov     r0, rINST, lsr #8           @ r0<- AA
1847    GET_VREG(r2, r0)                    @ r2<- vAA
1848    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1849    cmp     r2, #0                      @ compare (vA, 0)
1850    ble  1f                      @ branch to 1 if comparison failed
1851    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1852    movs    r9, r9, asl #1              @ convert to bytes, check sign
1853    bmi     common_backwardBranch       @ backward branch, do periodic checks
18541:
1855#if defined(WITH_JIT)
1856    GET_JIT_PROF_TABLE(r0)
1857    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1858    cmp     r0,#0
1859    bne     common_updateProfile
1860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1861    GOTO_OPCODE(ip)                     @ jump to next instruction
1862#else
1863    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1865    GOTO_OPCODE(ip)                     @ jump to next instruction
1866#endif
1867
1868
1869/* ------------------------------ */
1870    .balign 64
1871.L_OP_IF_LEZ: /* 0x3d */
1872/* File: armv5te/OP_IF_LEZ.S */
1873/* File: armv5te/zcmp.S */
1874    /*
1875     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1876     * fragment that specifies the *reverse* comparison to perform, e.g.
1877     * for "if-le" you would use "gt".
1878     *
1879     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1880     */
1881    /* if-cmp vAA, +BBBB */
1882    mov     r0, rINST, lsr #8           @ r0<- AA
1883    GET_VREG(r2, r0)                    @ r2<- vAA
1884    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1885    cmp     r2, #0                      @ compare (vA, 0)
1886    bgt  1f                      @ branch to 1 if comparison failed
1887    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1888    movs    r9, r9, asl #1              @ convert to bytes, check sign
1889    bmi     common_backwardBranch       @ backward branch, do periodic checks
18901:
1891#if defined(WITH_JIT)
1892    GET_JIT_PROF_TABLE(r0)
1893    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1894    cmp     r0,#0
1895    bne     common_updateProfile
1896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1897    GOTO_OPCODE(ip)                     @ jump to next instruction
1898#else
1899    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1901    GOTO_OPCODE(ip)                     @ jump to next instruction
1902#endif
1903
1904
1905/* ------------------------------ */
1906    .balign 64
1907.L_OP_UNUSED_3E: /* 0x3e */
1908/* File: armv5te/OP_UNUSED_3E.S */
1909/* File: armv5te/unused.S */
1910    bl      common_abort
1911
1912
1913/* ------------------------------ */
1914    .balign 64
1915.L_OP_UNUSED_3F: /* 0x3f */
1916/* File: armv5te/OP_UNUSED_3F.S */
1917/* File: armv5te/unused.S */
1918    bl      common_abort
1919
1920
1921/* ------------------------------ */
1922    .balign 64
1923.L_OP_UNUSED_40: /* 0x40 */
1924/* File: armv5te/OP_UNUSED_40.S */
1925/* File: armv5te/unused.S */
1926    bl      common_abort
1927
1928
1929/* ------------------------------ */
1930    .balign 64
1931.L_OP_UNUSED_41: /* 0x41 */
1932/* File: armv5te/OP_UNUSED_41.S */
1933/* File: armv5te/unused.S */
1934    bl      common_abort
1935
1936
1937/* ------------------------------ */
1938    .balign 64
1939.L_OP_UNUSED_42: /* 0x42 */
1940/* File: armv5te/OP_UNUSED_42.S */
1941/* File: armv5te/unused.S */
1942    bl      common_abort
1943
1944
1945/* ------------------------------ */
1946    .balign 64
1947.L_OP_UNUSED_43: /* 0x43 */
1948/* File: armv5te/OP_UNUSED_43.S */
1949/* File: armv5te/unused.S */
1950    bl      common_abort
1951
1952
1953/* ------------------------------ */
1954    .balign 64
1955.L_OP_AGET: /* 0x44 */
1956/* File: armv5te/OP_AGET.S */
1957    /*
1958     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1959     *
1960     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1961     * instructions.  We use a pair of FETCH_Bs instead.
1962     *
1963     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1964     */
1965    /* op vAA, vBB, vCC */
1966    FETCH_B(r2, 1, 0)                   @ r2<- BB
1967    mov     r9, rINST, lsr #8           @ r9<- AA
1968    FETCH_B(r3, 1, 1)                   @ r3<- CC
1969    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1970    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1971    cmp     r0, #0                      @ null array object?
1972    beq     common_errNullObject        @ yes, bail
1973    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1974    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1975    cmp     r1, r3                      @ compare unsigned index, length
1976    bcs     common_errArrayIndex        @ index >= length, bail
1977    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1978    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1980    SET_VREG(r2, r9)                    @ vAA<- r2
1981    GOTO_OPCODE(ip)                     @ jump to next instruction
1982
1983/* ------------------------------ */
1984    .balign 64
1985.L_OP_AGET_WIDE: /* 0x45 */
1986/* File: armv5te/OP_AGET_WIDE.S */
1987    /*
1988     * Array get, 64 bits.  vAA <- vBB[vCC].
1989     *
1990     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1991     */
1992    /* aget-wide vAA, vBB, vCC */
1993    FETCH(r0, 1)                        @ r0<- CCBB
1994    mov     r9, rINST, lsr #8           @ r9<- AA
1995    and     r2, r0, #255                @ r2<- BB
1996    mov     r3, r0, lsr #8              @ r3<- CC
1997    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1998    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1999    cmp     r0, #0                      @ null array object?
2000    beq     common_errNullObject        @ yes, bail
2001    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2002    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2003    cmp     r1, r3                      @ compare unsigned index, length
2004    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2005    b       common_errArrayIndex        @ index >= length, bail
2006    @ May want to swap the order of these two branches depending on how the
2007    @ branch prediction (if any) handles conditional forward branches vs.
2008    @ unconditional forward branches.
2009
2010/* ------------------------------ */
2011    .balign 64
2012.L_OP_AGET_OBJECT: /* 0x46 */
2013/* File: armv5te/OP_AGET_OBJECT.S */
2014/* File: armv5te/OP_AGET.S */
2015    /*
2016     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2017     *
2018     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2019     * instructions.  We use a pair of FETCH_Bs instead.
2020     *
2021     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2022     */
2023    /* op vAA, vBB, vCC */
2024    FETCH_B(r2, 1, 0)                   @ r2<- BB
2025    mov     r9, rINST, lsr #8           @ r9<- AA
2026    FETCH_B(r3, 1, 1)                   @ r3<- CC
2027    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2028    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2029    cmp     r0, #0                      @ null array object?
2030    beq     common_errNullObject        @ yes, bail
2031    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2032    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2033    cmp     r1, r3                      @ compare unsigned index, length
2034    bcs     common_errArrayIndex        @ index >= length, bail
2035    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2036    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2037    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2038    SET_VREG(r2, r9)                    @ vAA<- r2
2039    GOTO_OPCODE(ip)                     @ jump to next instruction
2040
2041
2042/* ------------------------------ */
2043    .balign 64
2044.L_OP_AGET_BOOLEAN: /* 0x47 */
2045/* File: armv5te/OP_AGET_BOOLEAN.S */
2046/* File: armv5te/OP_AGET.S */
2047    /*
2048     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2049     *
2050     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2051     * instructions.  We use a pair of FETCH_Bs instead.
2052     *
2053     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2054     */
2055    /* op vAA, vBB, vCC */
2056    FETCH_B(r2, 1, 0)                   @ r2<- BB
2057    mov     r9, rINST, lsr #8           @ r9<- AA
2058    FETCH_B(r3, 1, 1)                   @ r3<- CC
2059    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2060    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2061    cmp     r0, #0                      @ null array object?
2062    beq     common_errNullObject        @ yes, bail
2063    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2064    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2065    cmp     r1, r3                      @ compare unsigned index, length
2066    bcs     common_errArrayIndex        @ index >= length, bail
2067    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2068    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2070    SET_VREG(r2, r9)                    @ vAA<- r2
2071    GOTO_OPCODE(ip)                     @ jump to next instruction
2072
2073
2074/* ------------------------------ */
2075    .balign 64
2076.L_OP_AGET_BYTE: /* 0x48 */
2077/* File: armv5te/OP_AGET_BYTE.S */
2078/* File: armv5te/OP_AGET.S */
2079    /*
2080     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2081     *
2082     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2083     * instructions.  We use a pair of FETCH_Bs instead.
2084     *
2085     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2086     */
2087    /* op vAA, vBB, vCC */
2088    FETCH_B(r2, 1, 0)                   @ r2<- BB
2089    mov     r9, rINST, lsr #8           @ r9<- AA
2090    FETCH_B(r3, 1, 1)                   @ r3<- CC
2091    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2092    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2093    cmp     r0, #0                      @ null array object?
2094    beq     common_errNullObject        @ yes, bail
2095    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2096    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2097    cmp     r1, r3                      @ compare unsigned index, length
2098    bcs     common_errArrayIndex        @ index >= length, bail
2099    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2100    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2102    SET_VREG(r2, r9)                    @ vAA<- r2
2103    GOTO_OPCODE(ip)                     @ jump to next instruction
2104
2105
2106/* ------------------------------ */
2107    .balign 64
2108.L_OP_AGET_CHAR: /* 0x49 */
2109/* File: armv5te/OP_AGET_CHAR.S */
2110/* File: armv5te/OP_AGET.S */
2111    /*
2112     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2113     *
2114     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2115     * instructions.  We use a pair of FETCH_Bs instead.
2116     *
2117     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2118     */
2119    /* op vAA, vBB, vCC */
2120    FETCH_B(r2, 1, 0)                   @ r2<- BB
2121    mov     r9, rINST, lsr #8           @ r9<- AA
2122    FETCH_B(r3, 1, 1)                   @ r3<- CC
2123    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2124    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2125    cmp     r0, #0                      @ null array object?
2126    beq     common_errNullObject        @ yes, bail
2127    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2128    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2129    cmp     r1, r3                      @ compare unsigned index, length
2130    bcs     common_errArrayIndex        @ index >= length, bail
2131    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2132    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2134    SET_VREG(r2, r9)                    @ vAA<- r2
2135    GOTO_OPCODE(ip)                     @ jump to next instruction
2136
2137
2138/* ------------------------------ */
2139    .balign 64
2140.L_OP_AGET_SHORT: /* 0x4a */
2141/* File: armv5te/OP_AGET_SHORT.S */
2142/* File: armv5te/OP_AGET.S */
2143    /*
2144     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2145     *
2146     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2147     * instructions.  We use a pair of FETCH_Bs instead.
2148     *
2149     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2150     */
2151    /* op vAA, vBB, vCC */
2152    FETCH_B(r2, 1, 0)                   @ r2<- BB
2153    mov     r9, rINST, lsr #8           @ r9<- AA
2154    FETCH_B(r3, 1, 1)                   @ r3<- CC
2155    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2156    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2157    cmp     r0, #0                      @ null array object?
2158    beq     common_errNullObject        @ yes, bail
2159    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2160    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2161    cmp     r1, r3                      @ compare unsigned index, length
2162    bcs     common_errArrayIndex        @ index >= length, bail
2163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2164    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2166    SET_VREG(r2, r9)                    @ vAA<- r2
2167    GOTO_OPCODE(ip)                     @ jump to next instruction
2168
2169
2170/* ------------------------------ */
2171    .balign 64
2172.L_OP_APUT: /* 0x4b */
2173/* File: armv5te/OP_APUT.S */
2174    /*
2175     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2176     *
2177     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2178     * instructions.  We use a pair of FETCH_Bs instead.
2179     *
2180     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2181     */
2182    /* op vAA, vBB, vCC */
2183    FETCH_B(r2, 1, 0)                   @ r2<- BB
2184    mov     r9, rINST, lsr #8           @ r9<- AA
2185    FETCH_B(r3, 1, 1)                   @ r3<- CC
2186    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2187    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2188    cmp     r0, #0                      @ null array object?
2189    beq     common_errNullObject        @ yes, bail
2190    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2191    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2192    cmp     r1, r3                      @ compare unsigned index, length
2193    bcs     common_errArrayIndex        @ index >= length, bail
2194    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2195    GET_VREG(r2, r9)                    @ r2<- vAA
2196    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2197    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2198    GOTO_OPCODE(ip)                     @ jump to next instruction
2199
2200/* ------------------------------ */
2201    .balign 64
2202.L_OP_APUT_WIDE: /* 0x4c */
2203/* File: armv5te/OP_APUT_WIDE.S */
2204    /*
2205     * Array put, 64 bits.  vBB[vCC] <- vAA.
2206     *
2207     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2208     */
2209    /* aput-wide vAA, vBB, vCC */
2210    FETCH(r0, 1)                        @ r0<- CCBB
2211    mov     r9, rINST, lsr #8           @ r9<- AA
2212    and     r2, r0, #255                @ r2<- BB
2213    mov     r3, r0, lsr #8              @ r3<- CC
2214    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2215    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2216    cmp     r0, #0                      @ null array object?
2217    beq     common_errNullObject        @ yes, bail
2218    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2219    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2220    cmp     r1, r3                      @ compare unsigned index, length
2221    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2222    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2223    b       common_errArrayIndex        @ index >= length, bail
2224    @ May want to swap the order of these two branches depending on how the
2225    @ branch prediction (if any) handles conditional forward branches vs.
2226    @ unconditional forward branches.
2227
2228/* ------------------------------ */
2229    .balign 64
2230.L_OP_APUT_OBJECT: /* 0x4d */
2231/* File: armv5te/OP_APUT_OBJECT.S */
2232    /*
2233     * Store an object into an array.  vBB[vCC] <- vAA.
2234     */
2235    /* op vAA, vBB, vCC */
2236    FETCH(r0, 1)                        @ r0<- CCBB
2237    mov     r9, rINST, lsr #8           @ r9<- AA
2238    and     r2, r0, #255                @ r2<- BB
2239    mov     r3, r0, lsr #8              @ r3<- CC
2240    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2241    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2242    cmp     rINST, #0                   @ null array object?
2243    GET_VREG(r9, r9)                    @ r9<- vAA
2244    beq     common_errNullObject        @ yes, bail
2245    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2246    add     r10, rINST, r1, lsl #2      @ r10<- arrayObj + index*width
2247    cmp     r1, r3                      @ compare unsigned index, length
2248    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2249    b       common_errArrayIndex        @ index >= length, bail
2250
2251
2252/* ------------------------------ */
2253    .balign 64
2254.L_OP_APUT_BOOLEAN: /* 0x4e */
2255/* File: armv5te/OP_APUT_BOOLEAN.S */
2256/* File: armv5te/OP_APUT.S */
2257    /*
2258     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2259     *
2260     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2261     * instructions.  We use a pair of FETCH_Bs instead.
2262     *
2263     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2264     */
2265    /* op vAA, vBB, vCC */
2266    FETCH_B(r2, 1, 0)                   @ r2<- BB
2267    mov     r9, rINST, lsr #8           @ r9<- AA
2268    FETCH_B(r3, 1, 1)                   @ r3<- CC
2269    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2270    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2271    cmp     r0, #0                      @ null array object?
2272    beq     common_errNullObject        @ yes, bail
2273    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2274    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2275    cmp     r1, r3                      @ compare unsigned index, length
2276    bcs     common_errArrayIndex        @ index >= length, bail
2277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2278    GET_VREG(r2, r9)                    @ r2<- vAA
2279    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2280    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2281    GOTO_OPCODE(ip)                     @ jump to next instruction
2282
2283
2284/* ------------------------------ */
2285    .balign 64
2286.L_OP_APUT_BYTE: /* 0x4f */
2287/* File: armv5te/OP_APUT_BYTE.S */
2288/* File: armv5te/OP_APUT.S */
2289    /*
2290     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2291     *
2292     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2293     * instructions.  We use a pair of FETCH_Bs instead.
2294     *
2295     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2296     */
2297    /* op vAA, vBB, vCC */
2298    FETCH_B(r2, 1, 0)                   @ r2<- BB
2299    mov     r9, rINST, lsr #8           @ r9<- AA
2300    FETCH_B(r3, 1, 1)                   @ r3<- CC
2301    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2302    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2303    cmp     r0, #0                      @ null array object?
2304    beq     common_errNullObject        @ yes, bail
2305    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2306    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2307    cmp     r1, r3                      @ compare unsigned index, length
2308    bcs     common_errArrayIndex        @ index >= length, bail
2309    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2310    GET_VREG(r2, r9)                    @ r2<- vAA
2311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2312    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2313    GOTO_OPCODE(ip)                     @ jump to next instruction
2314
2315
2316/* ------------------------------ */
2317    .balign 64
2318.L_OP_APUT_CHAR: /* 0x50 */
2319/* File: armv5te/OP_APUT_CHAR.S */
2320/* File: armv5te/OP_APUT.S */
2321    /*
2322     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2323     *
2324     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2325     * instructions.  We use a pair of FETCH_Bs instead.
2326     *
2327     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2328     */
2329    /* op vAA, vBB, vCC */
2330    FETCH_B(r2, 1, 0)                   @ r2<- BB
2331    mov     r9, rINST, lsr #8           @ r9<- AA
2332    FETCH_B(r3, 1, 1)                   @ r3<- CC
2333    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2334    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2335    cmp     r0, #0                      @ null array object?
2336    beq     common_errNullObject        @ yes, bail
2337    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2338    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2339    cmp     r1, r3                      @ compare unsigned index, length
2340    bcs     common_errArrayIndex        @ index >= length, bail
2341    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2342    GET_VREG(r2, r9)                    @ r2<- vAA
2343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2344    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2345    GOTO_OPCODE(ip)                     @ jump to next instruction
2346
2347
2348/* ------------------------------ */
2349    .balign 64
2350.L_OP_APUT_SHORT: /* 0x51 */
2351/* File: armv5te/OP_APUT_SHORT.S */
2352/* File: armv5te/OP_APUT.S */
2353    /*
2354     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2355     *
2356     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2357     * instructions.  We use a pair of FETCH_Bs instead.
2358     *
2359     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2360     */
2361    /* op vAA, vBB, vCC */
2362    FETCH_B(r2, 1, 0)                   @ r2<- BB
2363    mov     r9, rINST, lsr #8           @ r9<- AA
2364    FETCH_B(r3, 1, 1)                   @ r3<- CC
2365    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2366    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2367    cmp     r0, #0                      @ null array object?
2368    beq     common_errNullObject        @ yes, bail
2369    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2370    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2371    cmp     r1, r3                      @ compare unsigned index, length
2372    bcs     common_errArrayIndex        @ index >= length, bail
2373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2374    GET_VREG(r2, r9)                    @ r2<- vAA
2375    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2376    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2377    GOTO_OPCODE(ip)                     @ jump to next instruction
2378
2379
2380/* ------------------------------ */
2381    .balign 64
2382.L_OP_IGET: /* 0x52 */
2383/* File: armv5te/OP_IGET.S */
2384    /*
2385     * General 32-bit instance field get.
2386     *
2387     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2388     */
2389    /* op vA, vB, field@CCCC */
2390    mov     r0, rINST, lsr #12          @ r0<- B
2391    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2392    FETCH(r1, 1)                        @ r1<- field ref CCCC
2393    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2394    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2395    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2396    cmp     r0, #0                      @ is resolved entry null?
2397    bne     .LOP_IGET_finish          @ no, already resolved
23988:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2399    EXPORT_PC()                         @ resolve() could throw
2400    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2401    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2402    cmp     r0, #0
2403    bne     .LOP_IGET_finish
2404    b       common_exceptionThrown
2405
2406/* ------------------------------ */
2407    .balign 64
2408.L_OP_IGET_WIDE: /* 0x53 */
2409/* File: armv5te/OP_IGET_WIDE.S */
2410    /*
2411     * Wide 32-bit instance field get.
2412     */
2413    /* iget-wide vA, vB, field@CCCC */
2414    mov     r0, rINST, lsr #12          @ r0<- B
2415    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2416    FETCH(r1, 1)                        @ r1<- field ref CCCC
2417    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2418    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2419    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2420    cmp     r0, #0                      @ is resolved entry null?
2421    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24228:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2423    EXPORT_PC()                         @ resolve() could throw
2424    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2425    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2426    cmp     r0, #0
2427    bne     .LOP_IGET_WIDE_finish
2428    b       common_exceptionThrown
2429
2430/* ------------------------------ */
2431    .balign 64
2432.L_OP_IGET_OBJECT: /* 0x54 */
2433/* File: armv5te/OP_IGET_OBJECT.S */
2434/* File: armv5te/OP_IGET.S */
2435    /*
2436     * General 32-bit instance field get.
2437     *
2438     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2439     */
2440    /* op vA, vB, field@CCCC */
2441    mov     r0, rINST, lsr #12          @ r0<- B
2442    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2443    FETCH(r1, 1)                        @ r1<- field ref CCCC
2444    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2445    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2446    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2447    cmp     r0, #0                      @ is resolved entry null?
2448    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24498:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2450    EXPORT_PC()                         @ resolve() could throw
2451    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2452    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2453    cmp     r0, #0
2454    bne     .LOP_IGET_OBJECT_finish
2455    b       common_exceptionThrown
2456
2457
2458/* ------------------------------ */
2459    .balign 64
2460.L_OP_IGET_BOOLEAN: /* 0x55 */
2461/* File: armv5te/OP_IGET_BOOLEAN.S */
2462@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2463/* File: armv5te/OP_IGET.S */
2464    /*
2465     * General 32-bit instance field get.
2466     *
2467     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2468     */
2469    /* op vA, vB, field@CCCC */
2470    mov     r0, rINST, lsr #12          @ r0<- B
2471    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2472    FETCH(r1, 1)                        @ r1<- field ref CCCC
2473    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2474    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2475    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2476    cmp     r0, #0                      @ is resolved entry null?
2477    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
24788:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2479    EXPORT_PC()                         @ resolve() could throw
2480    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2481    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2482    cmp     r0, #0
2483    bne     .LOP_IGET_BOOLEAN_finish
2484    b       common_exceptionThrown
2485
2486
2487/* ------------------------------ */
2488    .balign 64
2489.L_OP_IGET_BYTE: /* 0x56 */
2490/* File: armv5te/OP_IGET_BYTE.S */
2491@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2492/* File: armv5te/OP_IGET.S */
2493    /*
2494     * General 32-bit instance field get.
2495     *
2496     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2497     */
2498    /* op vA, vB, field@CCCC */
2499    mov     r0, rINST, lsr #12          @ r0<- B
2500    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2501    FETCH(r1, 1)                        @ r1<- field ref CCCC
2502    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2503    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2504    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2505    cmp     r0, #0                      @ is resolved entry null?
2506    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2508    EXPORT_PC()                         @ resolve() could throw
2509    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2510    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2511    cmp     r0, #0
2512    bne     .LOP_IGET_BYTE_finish
2513    b       common_exceptionThrown
2514
2515
2516/* ------------------------------ */
2517    .balign 64
2518.L_OP_IGET_CHAR: /* 0x57 */
2519/* File: armv5te/OP_IGET_CHAR.S */
2520@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2521/* File: armv5te/OP_IGET.S */
2522    /*
2523     * General 32-bit instance field get.
2524     *
2525     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2526     */
2527    /* op vA, vB, field@CCCC */
2528    mov     r0, rINST, lsr #12          @ r0<- B
2529    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2530    FETCH(r1, 1)                        @ r1<- field ref CCCC
2531    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2532    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2533    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2534    cmp     r0, #0                      @ is resolved entry null?
2535    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25368:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2537    EXPORT_PC()                         @ resolve() could throw
2538    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2539    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2540    cmp     r0, #0
2541    bne     .LOP_IGET_CHAR_finish
2542    b       common_exceptionThrown
2543
2544
2545/* ------------------------------ */
2546    .balign 64
2547.L_OP_IGET_SHORT: /* 0x58 */
2548/* File: armv5te/OP_IGET_SHORT.S */
2549@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2550/* File: armv5te/OP_IGET.S */
2551    /*
2552     * General 32-bit instance field get.
2553     *
2554     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2555     */
2556    /* op vA, vB, field@CCCC */
2557    mov     r0, rINST, lsr #12          @ r0<- B
2558    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2559    FETCH(r1, 1)                        @ r1<- field ref CCCC
2560    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2561    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2562    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2563    cmp     r0, #0                      @ is resolved entry null?
2564    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25658:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2566    EXPORT_PC()                         @ resolve() could throw
2567    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2568    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2569    cmp     r0, #0
2570    bne     .LOP_IGET_SHORT_finish
2571    b       common_exceptionThrown
2572
2573
2574/* ------------------------------ */
2575    .balign 64
2576.L_OP_IPUT: /* 0x59 */
2577/* File: armv5te/OP_IPUT.S */
2578    /*
2579     * General 32-bit instance field put.
2580     *
2581     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2582     */
2583    /* op vA, vB, field@CCCC */
2584    mov     r0, rINST, lsr #12          @ r0<- B
2585    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2586    FETCH(r1, 1)                        @ r1<- field ref CCCC
2587    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2588    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2589    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2590    cmp     r0, #0                      @ is resolved entry null?
2591    bne     .LOP_IPUT_finish          @ no, already resolved
25928:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2593    EXPORT_PC()                         @ resolve() could throw
2594    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2595    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2596    cmp     r0, #0                      @ success?
2597    bne     .LOP_IPUT_finish          @ yes, finish up
2598    b       common_exceptionThrown
2599
2600/* ------------------------------ */
2601    .balign 64
2602.L_OP_IPUT_WIDE: /* 0x5a */
2603/* File: armv5te/OP_IPUT_WIDE.S */
2604    /* iput-wide vA, vB, field@CCCC */
2605    mov     r0, rINST, lsr #12          @ r0<- B
2606    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2607    FETCH(r1, 1)                        @ r1<- field ref CCCC
2608    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2609    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2610    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2611    cmp     r0, #0                      @ is resolved entry null?
2612    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26138:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2614    EXPORT_PC()                         @ resolve() could throw
2615    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2616    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2617    cmp     r0, #0                      @ success?
2618    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2619    b       common_exceptionThrown
2620
2621/* ------------------------------ */
2622    .balign 64
2623.L_OP_IPUT_OBJECT: /* 0x5b */
2624/* File: armv5te/OP_IPUT_OBJECT.S */
2625    /*
2626     * 32-bit instance field put.
2627     *
2628     * for: iput-object, iput-object-volatile
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_OBJECT_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_OBJECT_finish          @ yes, finish up
2645    b       common_exceptionThrown
2646
2647/* ------------------------------ */
2648    .balign 64
2649.L_OP_IPUT_BOOLEAN: /* 0x5c */
2650/* File: armv5te/OP_IPUT_BOOLEAN.S */
2651@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2652/* File: armv5te/OP_IPUT.S */
2653    /*
2654     * General 32-bit instance field put.
2655     *
2656     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2657     */
2658    /* op vA, vB, field@CCCC */
2659    mov     r0, rINST, lsr #12          @ r0<- B
2660    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2661    FETCH(r1, 1)                        @ r1<- field ref CCCC
2662    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2663    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2664    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2665    cmp     r0, #0                      @ is resolved entry null?
2666    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26678:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2668    EXPORT_PC()                         @ resolve() could throw
2669    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2670    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2671    cmp     r0, #0                      @ success?
2672    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2673    b       common_exceptionThrown
2674
2675
2676/* ------------------------------ */
2677    .balign 64
2678.L_OP_IPUT_BYTE: /* 0x5d */
2679/* File: armv5te/OP_IPUT_BYTE.S */
2680@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2681/* File: armv5te/OP_IPUT.S */
2682    /*
2683     * General 32-bit instance field put.
2684     *
2685     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2686     */
2687    /* op vA, vB, field@CCCC */
2688    mov     r0, rINST, lsr #12          @ r0<- B
2689    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2690    FETCH(r1, 1)                        @ r1<- field ref CCCC
2691    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2692    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2693    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2694    cmp     r0, #0                      @ is resolved entry null?
2695    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
26968:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2697    EXPORT_PC()                         @ resolve() could throw
2698    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2699    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2700    cmp     r0, #0                      @ success?
2701    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2702    b       common_exceptionThrown
2703
2704
2705/* ------------------------------ */
2706    .balign 64
2707.L_OP_IPUT_CHAR: /* 0x5e */
2708/* File: armv5te/OP_IPUT_CHAR.S */
2709@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2710/* File: armv5te/OP_IPUT.S */
2711    /*
2712     * General 32-bit instance field put.
2713     *
2714     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2715     */
2716    /* op vA, vB, field@CCCC */
2717    mov     r0, rINST, lsr #12          @ r0<- B
2718    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2719    FETCH(r1, 1)                        @ r1<- field ref CCCC
2720    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2721    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2722    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2723    cmp     r0, #0                      @ is resolved entry null?
2724    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27258:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2726    EXPORT_PC()                         @ resolve() could throw
2727    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2728    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2729    cmp     r0, #0                      @ success?
2730    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2731    b       common_exceptionThrown
2732
2733
2734/* ------------------------------ */
2735    .balign 64
2736.L_OP_IPUT_SHORT: /* 0x5f */
2737/* File: armv5te/OP_IPUT_SHORT.S */
2738@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2739/* File: armv5te/OP_IPUT.S */
2740    /*
2741     * General 32-bit instance field put.
2742     *
2743     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2744     */
2745    /* op vA, vB, field@CCCC */
2746    mov     r0, rINST, lsr #12          @ r0<- B
2747    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2748    FETCH(r1, 1)                        @ r1<- field ref CCCC
2749    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2750    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2751    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2752    cmp     r0, #0                      @ is resolved entry null?
2753    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27548:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2755    EXPORT_PC()                         @ resolve() could throw
2756    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2757    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2758    cmp     r0, #0                      @ success?
2759    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2760    b       common_exceptionThrown
2761
2762
2763/* ------------------------------ */
2764    .balign 64
2765.L_OP_SGET: /* 0x60 */
2766/* File: armv5te/OP_SGET.S */
2767    /*
2768     * General 32-bit SGET handler.
2769     *
2770     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2771     */
2772    /* op vAA, field@BBBB */
2773    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2774    FETCH(r1, 1)                        @ r1<- field ref BBBB
2775    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2776    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2777    cmp     r0, #0                      @ is resolved entry null?
2778    beq     .LOP_SGET_resolve         @ yes, do resolve
2779.LOP_SGET_finish: @ field ptr in r0
2780    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2781    @ no-op                             @ acquiring load
2782    mov     r2, rINST, lsr #8           @ r2<- AA
2783    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2784    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2785    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2786    GOTO_OPCODE(ip)                     @ jump to next instruction
2787
2788/* ------------------------------ */
2789    .balign 64
2790.L_OP_SGET_WIDE: /* 0x61 */
2791/* File: armv5te/OP_SGET_WIDE.S */
2792    /*
2793     * 64-bit SGET handler.
2794     */
2795    /* sget-wide vAA, field@BBBB */
2796    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2797    FETCH(r1, 1)                        @ r1<- field ref BBBB
2798    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2799    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2800    cmp     r0, #0                      @ is resolved entry null?
2801    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2802.LOP_SGET_WIDE_finish:
2803    mov     r9, rINST, lsr #8           @ r9<- AA
2804    .if 0
2805    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2806    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2807    .else
2808    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2809    .endif
2810    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2811    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2812    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2813    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2814    GOTO_OPCODE(ip)                     @ jump to next instruction
2815
2816/* ------------------------------ */
2817    .balign 64
2818.L_OP_SGET_OBJECT: /* 0x62 */
2819/* File: armv5te/OP_SGET_OBJECT.S */
2820/* File: armv5te/OP_SGET.S */
2821    /*
2822     * General 32-bit SGET handler.
2823     *
2824     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2825     */
2826    /* op vAA, field@BBBB */
2827    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2828    FETCH(r1, 1)                        @ r1<- field ref BBBB
2829    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2830    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2831    cmp     r0, #0                      @ is resolved entry null?
2832    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2833.LOP_SGET_OBJECT_finish: @ field ptr in r0
2834    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2835    @ no-op                             @ acquiring load
2836    mov     r2, rINST, lsr #8           @ r2<- AA
2837    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2838    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2840    GOTO_OPCODE(ip)                     @ jump to next instruction
2841
2842
2843/* ------------------------------ */
2844    .balign 64
2845.L_OP_SGET_BOOLEAN: /* 0x63 */
2846/* File: armv5te/OP_SGET_BOOLEAN.S */
2847/* File: armv5te/OP_SGET.S */
2848    /*
2849     * General 32-bit SGET handler.
2850     *
2851     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2852     */
2853    /* op vAA, field@BBBB */
2854    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2855    FETCH(r1, 1)                        @ r1<- field ref BBBB
2856    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858    cmp     r0, #0                      @ is resolved entry null?
2859    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2860.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2861    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2862    @ no-op                             @ acquiring load
2863    mov     r2, rINST, lsr #8           @ r2<- AA
2864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867    GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869
2870/* ------------------------------ */
2871    .balign 64
2872.L_OP_SGET_BYTE: /* 0x64 */
2873/* File: armv5te/OP_SGET_BYTE.S */
2874/* File: armv5te/OP_SGET.S */
2875    /*
2876     * General 32-bit SGET handler.
2877     *
2878     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2879     */
2880    /* op vAA, field@BBBB */
2881    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2882    FETCH(r1, 1)                        @ r1<- field ref BBBB
2883    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2885    cmp     r0, #0                      @ is resolved entry null?
2886    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2887.LOP_SGET_BYTE_finish: @ field ptr in r0
2888    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2889    @ no-op                             @ acquiring load
2890    mov     r2, rINST, lsr #8           @ r2<- AA
2891    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2892    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2894    GOTO_OPCODE(ip)                     @ jump to next instruction
2895
2896
2897/* ------------------------------ */
2898    .balign 64
2899.L_OP_SGET_CHAR: /* 0x65 */
2900/* File: armv5te/OP_SGET_CHAR.S */
2901/* File: armv5te/OP_SGET.S */
2902    /*
2903     * General 32-bit SGET handler.
2904     *
2905     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2906     */
2907    /* op vAA, field@BBBB */
2908    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2909    FETCH(r1, 1)                        @ r1<- field ref BBBB
2910    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2911    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2912    cmp     r0, #0                      @ is resolved entry null?
2913    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2914.LOP_SGET_CHAR_finish: @ field ptr in r0
2915    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2916    @ no-op                             @ acquiring load
2917    mov     r2, rINST, lsr #8           @ r2<- AA
2918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2919    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2921    GOTO_OPCODE(ip)                     @ jump to next instruction
2922
2923
2924/* ------------------------------ */
2925    .balign 64
2926.L_OP_SGET_SHORT: /* 0x66 */
2927/* File: armv5te/OP_SGET_SHORT.S */
2928/* File: armv5te/OP_SGET.S */
2929    /*
2930     * General 32-bit SGET handler.
2931     *
2932     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2933     */
2934    /* op vAA, field@BBBB */
2935    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2936    FETCH(r1, 1)                        @ r1<- field ref BBBB
2937    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2939    cmp     r0, #0                      @ is resolved entry null?
2940    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2941.LOP_SGET_SHORT_finish: @ field ptr in r0
2942    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2943    @ no-op                             @ acquiring load
2944    mov     r2, rINST, lsr #8           @ r2<- AA
2945    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948    GOTO_OPCODE(ip)                     @ jump to next instruction
2949
2950
2951/* ------------------------------ */
2952    .balign 64
2953.L_OP_SPUT: /* 0x67 */
2954/* File: armv5te/OP_SPUT.S */
2955    /*
2956     * General 32-bit SPUT handler.
2957     *
2958     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2959     */
2960    /* op vAA, field@BBBB */
2961    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2962    FETCH(r1, 1)                        @ r1<- field ref BBBB
2963    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2964    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2965    cmp     r0, #0                      @ is resolved entry null?
2966    beq     .LOP_SPUT_resolve         @ yes, do resolve
2967.LOP_SPUT_finish:   @ field ptr in r0
2968    mov     r2, rINST, lsr #8           @ r2<- AA
2969    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2970    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2971    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2972    @ no-op                             @ releasing store
2973    str     r1, [r0, #offStaticField_value] @ field<- vAA
2974    GOTO_OPCODE(ip)                     @ jump to next instruction
2975
2976/* ------------------------------ */
2977    .balign 64
2978.L_OP_SPUT_WIDE: /* 0x68 */
2979/* File: armv5te/OP_SPUT_WIDE.S */
2980    /*
2981     * 64-bit SPUT handler.
2982     */
2983    /* sput-wide vAA, field@BBBB */
2984    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
2985    FETCH(r1, 1)                        @ r1<- field ref BBBB
2986    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
2987    mov     r9, rINST, lsr #8           @ r9<- AA
2988    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
2989    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2990    cmp     r2, #0                      @ is resolved entry null?
2991    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2992.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
2993    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2994    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
2995    GET_INST_OPCODE(r10)                @ extract opcode from rINST
2996    .if 0
2997    add     r2, r2, #offStaticField_value @ r2<- pointer to data
2998    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
2999    .else
3000    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3001    .endif
3002    GOTO_OPCODE(r10)                    @ jump to next instruction
3003
3004/* ------------------------------ */
3005    .balign 64
3006.L_OP_SPUT_OBJECT: /* 0x69 */
3007/* File: armv5te/OP_SPUT_OBJECT.S */
3008    /*
3009     * 32-bit SPUT handler for objects
3010     *
3011     * for: sput-object, sput-object-volatile
3012     */
3013    /* op vAA, field@BBBB */
3014    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3015    FETCH(r1, 1)                        @ r1<- field ref BBBB
3016    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3017    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3018    cmp     r0, #0                      @ is resolved entry null?
3019    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3020    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3021    EXPORT_PC()                         @ resolve() could throw, so export now
3022    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3023    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3024    cmp     r0, #0                      @ success?
3025    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3026    b       common_exceptionThrown      @ no, handle exception
3027
3028
3029/* ------------------------------ */
3030    .balign 64
3031.L_OP_SPUT_BOOLEAN: /* 0x6a */
3032/* File: armv5te/OP_SPUT_BOOLEAN.S */
3033/* File: armv5te/OP_SPUT.S */
3034    /*
3035     * General 32-bit SPUT handler.
3036     *
3037     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3038     */
3039    /* op vAA, field@BBBB */
3040    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3041    FETCH(r1, 1)                        @ r1<- field ref BBBB
3042    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3043    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3044    cmp     r0, #0                      @ is resolved entry null?
3045    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3046.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3047    mov     r2, rINST, lsr #8           @ r2<- AA
3048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3049    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3051    @ no-op                             @ releasing store
3052    str     r1, [r0, #offStaticField_value] @ field<- vAA
3053    GOTO_OPCODE(ip)                     @ jump to next instruction
3054
3055
3056/* ------------------------------ */
3057    .balign 64
3058.L_OP_SPUT_BYTE: /* 0x6b */
3059/* File: armv5te/OP_SPUT_BYTE.S */
3060/* File: armv5te/OP_SPUT.S */
3061    /*
3062     * General 32-bit SPUT handler.
3063     *
3064     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3065     */
3066    /* op vAA, field@BBBB */
3067    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3068    FETCH(r1, 1)                        @ r1<- field ref BBBB
3069    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3070    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3071    cmp     r0, #0                      @ is resolved entry null?
3072    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3073.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3074    mov     r2, rINST, lsr #8           @ r2<- AA
3075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3076    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3078    @ no-op                             @ releasing store
3079    str     r1, [r0, #offStaticField_value] @ field<- vAA
3080    GOTO_OPCODE(ip)                     @ jump to next instruction
3081
3082
3083/* ------------------------------ */
3084    .balign 64
3085.L_OP_SPUT_CHAR: /* 0x6c */
3086/* File: armv5te/OP_SPUT_CHAR.S */
3087/* File: armv5te/OP_SPUT.S */
3088    /*
3089     * General 32-bit SPUT handler.
3090     *
3091     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3092     */
3093    /* op vAA, field@BBBB */
3094    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3095    FETCH(r1, 1)                        @ r1<- field ref BBBB
3096    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3097    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3098    cmp     r0, #0                      @ is resolved entry null?
3099    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3100.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3101    mov     r2, rINST, lsr #8           @ r2<- AA
3102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3103    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3105    @ no-op                             @ releasing store
3106    str     r1, [r0, #offStaticField_value] @ field<- vAA
3107    GOTO_OPCODE(ip)                     @ jump to next instruction
3108
3109
3110/* ------------------------------ */
3111    .balign 64
3112.L_OP_SPUT_SHORT: /* 0x6d */
3113/* File: armv5te/OP_SPUT_SHORT.S */
3114/* File: armv5te/OP_SPUT.S */
3115    /*
3116     * General 32-bit SPUT handler.
3117     *
3118     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3119     */
3120    /* op vAA, field@BBBB */
3121    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3122    FETCH(r1, 1)                        @ r1<- field ref BBBB
3123    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3124    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3125    cmp     r0, #0                      @ is resolved entry null?
3126    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3127.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3128    mov     r2, rINST, lsr #8           @ r2<- AA
3129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3130    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3131    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3132    @ no-op                             @ releasing store
3133    str     r1, [r0, #offStaticField_value] @ field<- vAA
3134    GOTO_OPCODE(ip)                     @ jump to next instruction
3135
3136
3137/* ------------------------------ */
3138    .balign 64
3139.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3140/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3141    /*
3142     * Handle a virtual method call.
3143     *
3144     * for: invoke-virtual, invoke-virtual/range
3145     */
3146    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3147    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3148    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3149    FETCH(r1, 1)                        @ r1<- BBBB
3150    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3151    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3152    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3153    .if     (!0)
3154    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3155    .endif
3156    cmp     r0, #0                      @ already resolved?
3157    EXPORT_PC()                         @ must export for invoke
3158    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3159    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3160    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3161    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3162    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3163    cmp     r0, #0                      @ got null?
3164    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3165    b       common_exceptionThrown      @ yes, handle exception
3166
3167/* ------------------------------ */
3168    .balign 64
3169.L_OP_INVOKE_SUPER: /* 0x6f */
3170/* File: armv5te/OP_INVOKE_SUPER.S */
3171    /*
3172     * Handle a "super" method call.
3173     *
3174     * for: invoke-super, invoke-super/range
3175     */
3176    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3179    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3180    .if     (!0)
3181    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3182    .endif
3183    FETCH(r1, 1)                        @ r1<- BBBB
3184    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3185    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3186    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3187    cmp     r2, #0                      @ null "this"?
3188    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3189    beq     common_errNullObject        @ null "this", throw exception
3190    cmp     r0, #0                      @ already resolved?
3191    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3192    EXPORT_PC()                         @ must export for invoke
3193    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3194    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3195
3196/* ------------------------------ */
3197    .balign 64
3198.L_OP_INVOKE_DIRECT: /* 0x70 */
3199/* File: armv5te/OP_INVOKE_DIRECT.S */
3200    /*
3201     * Handle a direct method call.
3202     *
3203     * (We could defer the "is 'this' pointer null" test to the common
3204     * method invocation code, and use a flag to indicate that static
3205     * calls don't count.  If we do this as part of copying the arguments
3206     * out we could avoiding loading the first arg twice.)
3207     *
3208     * for: invoke-direct, invoke-direct/range
3209     */
3210    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3211    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3212    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3213    FETCH(r1, 1)                        @ r1<- BBBB
3214    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3215    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3216    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3217    .if     (!0)
3218    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3219    .endif
3220    cmp     r0, #0                      @ already resolved?
3221    EXPORT_PC()                         @ must export for invoke
3222    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3223    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3224.LOP_INVOKE_DIRECT_finish:
3225    cmp     r2, #0                      @ null "this" ref?
3226    bne     common_invokeMethodNoRange   @ no, continue on
3227    b       common_errNullObject        @ yes, throw exception
3228
3229/* ------------------------------ */
3230    .balign 64
3231.L_OP_INVOKE_STATIC: /* 0x71 */
3232/* File: armv5te/OP_INVOKE_STATIC.S */
3233    /*
3234     * Handle a static method call.
3235     *
3236     * for: invoke-static, invoke-static/range
3237     */
3238    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3239    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3240    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3241    FETCH(r1, 1)                        @ r1<- BBBB
3242    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3243    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3244    cmp     r0, #0                      @ already resolved?
3245    EXPORT_PC()                         @ must export for invoke
3246    bne     common_invokeMethodNoRange @ yes, continue on
32470:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3248    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3249    mov     r2, #METHOD_STATIC          @ resolver method type
3250    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3251    cmp     r0, #0                      @ got null?
3252    bne     common_invokeMethodNoRange @ no, continue
3253    b       common_exceptionThrown      @ yes, handle exception
3254
3255/* ------------------------------ */
3256    .balign 64
3257.L_OP_INVOKE_INTERFACE: /* 0x72 */
3258/* File: armv5te/OP_INVOKE_INTERFACE.S */
3259    /*
3260     * Handle an interface method call.
3261     *
3262     * for: invoke-interface, invoke-interface/range
3263     */
3264    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3265    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3266    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3267    FETCH(r1, 1)                        @ r1<- BBBB
3268    .if     (!0)
3269    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3270    .endif
3271    EXPORT_PC()                         @ must export for invoke
3272    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3273    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3274    cmp     r0, #0                      @ null obj?
3275    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3276    beq     common_errNullObject        @ yes, fail
3277    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3278    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3279    cmp     r0, #0                      @ failed?
3280    beq     common_exceptionThrown      @ yes, handle exception
3281    b       common_invokeMethodNoRange @ jump to common handler
3282
3283/* ------------------------------ */
3284    .balign 64
3285.L_OP_UNUSED_73: /* 0x73 */
3286/* File: armv5te/OP_UNUSED_73.S */
3287/* File: armv5te/unused.S */
3288    bl      common_abort
3289
3290
3291/* ------------------------------ */
3292    .balign 64
3293.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3294/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3295/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3296    /*
3297     * Handle a virtual method call.
3298     *
3299     * for: invoke-virtual, invoke-virtual/range
3300     */
3301    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3304    FETCH(r1, 1)                        @ r1<- BBBB
3305    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3306    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3307    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3308    .if     (!1)
3309    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3310    .endif
3311    cmp     r0, #0                      @ already resolved?
3312    EXPORT_PC()                         @ must export for invoke
3313    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3314    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3315    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3316    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3317    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3318    cmp     r0, #0                      @ got null?
3319    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3320    b       common_exceptionThrown      @ yes, handle exception
3321
3322
3323/* ------------------------------ */
3324    .balign 64
3325.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3326/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3327/* File: armv5te/OP_INVOKE_SUPER.S */
3328    /*
3329     * Handle a "super" method call.
3330     *
3331     * for: invoke-super, invoke-super/range
3332     */
3333    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3334    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3335    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3336    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3337    .if     (!1)
3338    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3339    .endif
3340    FETCH(r1, 1)                        @ r1<- BBBB
3341    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3342    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3343    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3344    cmp     r2, #0                      @ null "this"?
3345    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3346    beq     common_errNullObject        @ null "this", throw exception
3347    cmp     r0, #0                      @ already resolved?
3348    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3349    EXPORT_PC()                         @ must export for invoke
3350    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3351    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3352
3353
3354/* ------------------------------ */
3355    .balign 64
3356.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3357/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3358/* File: armv5te/OP_INVOKE_DIRECT.S */
3359    /*
3360     * Handle a direct method call.
3361     *
3362     * (We could defer the "is 'this' pointer null" test to the common
3363     * method invocation code, and use a flag to indicate that static
3364     * calls don't count.  If we do this as part of copying the arguments
3365     * out we could avoiding loading the first arg twice.)
3366     *
3367     * for: invoke-direct, invoke-direct/range
3368     */
3369    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3370    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3371    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3372    FETCH(r1, 1)                        @ r1<- BBBB
3373    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3374    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3375    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3376    .if     (!1)
3377    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3378    .endif
3379    cmp     r0, #0                      @ already resolved?
3380    EXPORT_PC()                         @ must export for invoke
3381    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3382    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3383.LOP_INVOKE_DIRECT_RANGE_finish:
3384    cmp     r2, #0                      @ null "this" ref?
3385    bne     common_invokeMethodRange   @ no, continue on
3386    b       common_errNullObject        @ yes, throw exception
3387
3388
3389/* ------------------------------ */
3390    .balign 64
3391.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3392/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3393/* File: armv5te/OP_INVOKE_STATIC.S */
3394    /*
3395     * Handle a static method call.
3396     *
3397     * for: invoke-static, invoke-static/range
3398     */
3399    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3400    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3401    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3402    FETCH(r1, 1)                        @ r1<- BBBB
3403    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3404    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3405    cmp     r0, #0                      @ already resolved?
3406    EXPORT_PC()                         @ must export for invoke
3407    bne     common_invokeMethodRange @ yes, continue on
34080:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3409    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3410    mov     r2, #METHOD_STATIC          @ resolver method type
3411    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3412    cmp     r0, #0                      @ got null?
3413    bne     common_invokeMethodRange @ no, continue
3414    b       common_exceptionThrown      @ yes, handle exception
3415
3416
3417/* ------------------------------ */
3418    .balign 64
3419.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3420/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3421/* File: armv5te/OP_INVOKE_INTERFACE.S */
3422    /*
3423     * Handle an interface method call.
3424     *
3425     * for: invoke-interface, invoke-interface/range
3426     */
3427    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3428    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3429    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3430    FETCH(r1, 1)                        @ r1<- BBBB
3431    .if     (!1)
3432    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3433    .endif
3434    EXPORT_PC()                         @ must export for invoke
3435    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3436    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3437    cmp     r0, #0                      @ null obj?
3438    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3439    beq     common_errNullObject        @ yes, fail
3440    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3441    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3442    cmp     r0, #0                      @ failed?
3443    beq     common_exceptionThrown      @ yes, handle exception
3444    b       common_invokeMethodRange @ jump to common handler
3445
3446
3447/* ------------------------------ */
3448    .balign 64
3449.L_OP_UNUSED_79: /* 0x79 */
3450/* File: armv5te/OP_UNUSED_79.S */
3451/* File: armv5te/unused.S */
3452    bl      common_abort
3453
3454
3455/* ------------------------------ */
3456    .balign 64
3457.L_OP_UNUSED_7A: /* 0x7a */
3458/* File: armv5te/OP_UNUSED_7A.S */
3459/* File: armv5te/unused.S */
3460    bl      common_abort
3461
3462
3463/* ------------------------------ */
3464    .balign 64
3465.L_OP_NEG_INT: /* 0x7b */
3466/* File: armv5te/OP_NEG_INT.S */
3467/* File: armv5te/unop.S */
3468    /*
3469     * Generic 32-bit unary operation.  Provide an "instr" line that
3470     * specifies an instruction that performs "result = op r0".
3471     * This could be an ARM instruction or a function call.
3472     *
3473     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3474     *      int-to-byte, int-to-char, int-to-short
3475     */
3476    /* unop vA, vB */
3477    mov     r3, rINST, lsr #12          @ r3<- B
3478    mov     r9, rINST, lsr #8           @ r9<- A+
3479    GET_VREG(r0, r3)                    @ r0<- vB
3480    and     r9, r9, #15
3481                               @ optional op; may set condition codes
3482    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3483    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3484    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3485    SET_VREG(r0, r9)                    @ vAA<- r0
3486    GOTO_OPCODE(ip)                     @ jump to next instruction
3487    /* 9-10 instructions */
3488
3489
3490/* ------------------------------ */
3491    .balign 64
3492.L_OP_NOT_INT: /* 0x7c */
3493/* File: armv5te/OP_NOT_INT.S */
3494/* File: armv5te/unop.S */
3495    /*
3496     * Generic 32-bit unary operation.  Provide an "instr" line that
3497     * specifies an instruction that performs "result = op r0".
3498     * This could be an ARM instruction or a function call.
3499     *
3500     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3501     *      int-to-byte, int-to-char, int-to-short
3502     */
3503    /* unop vA, vB */
3504    mov     r3, rINST, lsr #12          @ r3<- B
3505    mov     r9, rINST, lsr #8           @ r9<- A+
3506    GET_VREG(r0, r3)                    @ r0<- vB
3507    and     r9, r9, #15
3508                               @ optional op; may set condition codes
3509    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3510    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3512    SET_VREG(r0, r9)                    @ vAA<- r0
3513    GOTO_OPCODE(ip)                     @ jump to next instruction
3514    /* 9-10 instructions */
3515
3516
3517/* ------------------------------ */
3518    .balign 64
3519.L_OP_NEG_LONG: /* 0x7d */
3520/* File: armv5te/OP_NEG_LONG.S */
3521/* File: armv5te/unopWide.S */
3522    /*
3523     * Generic 64-bit unary operation.  Provide an "instr" line that
3524     * specifies an instruction that performs "result = op r0/r1".
3525     * This could be an ARM instruction or a function call.
3526     *
3527     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3528     */
3529    /* unop vA, vB */
3530    mov     r9, rINST, lsr #8           @ r9<- A+
3531    mov     r3, rINST, lsr #12          @ r3<- B
3532    and     r9, r9, #15
3533    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3534    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3535    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3536    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3537    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3538    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3539    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3540    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3541    GOTO_OPCODE(ip)                     @ jump to next instruction
3542    /* 12-13 instructions */
3543
3544
3545/* ------------------------------ */
3546    .balign 64
3547.L_OP_NOT_LONG: /* 0x7e */
3548/* File: armv5te/OP_NOT_LONG.S */
3549/* File: armv5te/unopWide.S */
3550    /*
3551     * Generic 64-bit unary operation.  Provide an "instr" line that
3552     * specifies an instruction that performs "result = op r0/r1".
3553     * This could be an ARM instruction or a function call.
3554     *
3555     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3556     */
3557    /* unop vA, vB */
3558    mov     r9, rINST, lsr #8           @ r9<- A+
3559    mov     r3, rINST, lsr #12          @ r3<- B
3560    and     r9, r9, #15
3561    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3562    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3563    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3564    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3565    mvn     r0, r0                           @ optional op; may set condition codes
3566    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3568    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3569    GOTO_OPCODE(ip)                     @ jump to next instruction
3570    /* 12-13 instructions */
3571
3572
3573/* ------------------------------ */
3574    .balign 64
3575.L_OP_NEG_FLOAT: /* 0x7f */
3576/* File: armv5te/OP_NEG_FLOAT.S */
3577/* File: armv5te/unop.S */
3578    /*
3579     * Generic 32-bit unary operation.  Provide an "instr" line that
3580     * specifies an instruction that performs "result = op r0".
3581     * This could be an ARM instruction or a function call.
3582     *
3583     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3584     *      int-to-byte, int-to-char, int-to-short
3585     */
3586    /* unop vA, vB */
3587    mov     r3, rINST, lsr #12          @ r3<- B
3588    mov     r9, rINST, lsr #8           @ r9<- A+
3589    GET_VREG(r0, r3)                    @ r0<- vB
3590    and     r9, r9, #15
3591                               @ optional op; may set condition codes
3592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3593    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3594    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3595    SET_VREG(r0, r9)                    @ vAA<- r0
3596    GOTO_OPCODE(ip)                     @ jump to next instruction
3597    /* 9-10 instructions */
3598
3599
3600/* ------------------------------ */
3601    .balign 64
3602.L_OP_NEG_DOUBLE: /* 0x80 */
3603/* File: armv5te/OP_NEG_DOUBLE.S */
3604/* File: armv5te/unopWide.S */
3605    /*
3606     * Generic 64-bit unary operation.  Provide an "instr" line that
3607     * specifies an instruction that performs "result = op r0/r1".
3608     * This could be an ARM instruction or a function call.
3609     *
3610     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3611     */
3612    /* unop vA, vB */
3613    mov     r9, rINST, lsr #8           @ r9<- A+
3614    mov     r3, rINST, lsr #12          @ r3<- B
3615    and     r9, r9, #15
3616    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3617    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3618    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3619    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3620                               @ optional op; may set condition codes
3621    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3623    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3624    GOTO_OPCODE(ip)                     @ jump to next instruction
3625    /* 12-13 instructions */
3626
3627
3628/* ------------------------------ */
3629    .balign 64
3630.L_OP_INT_TO_LONG: /* 0x81 */
3631/* File: armv5te/OP_INT_TO_LONG.S */
3632/* File: armv5te/unopWider.S */
3633    /*
3634     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3635     * that specifies an instruction that performs "result = op r0", where
3636     * "result" is a 64-bit quantity in r0/r1.
3637     *
3638     * For: int-to-long, int-to-double, float-to-long, float-to-double
3639     */
3640    /* unop vA, vB */
3641    mov     r9, rINST, lsr #8           @ r9<- A+
3642    mov     r3, rINST, lsr #12          @ r3<- B
3643    and     r9, r9, #15
3644    GET_VREG(r0, r3)                    @ r0<- vB
3645    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3646                               @ optional op; may set condition codes
3647    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3648    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3650    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3651    GOTO_OPCODE(ip)                     @ jump to next instruction
3652    /* 10-11 instructions */
3653
3654
3655/* ------------------------------ */
3656    .balign 64
3657.L_OP_INT_TO_FLOAT: /* 0x82 */
3658/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3659/* File: arm-vfp/funop.S */
3660    /*
3661     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3662     * line that specifies an instruction that performs "s1 = op s0".
3663     *
3664     * for: int-to-float, float-to-int
3665     */
3666    /* unop vA, vB */
3667    mov     r3, rINST, lsr #12          @ r3<- B
3668    mov     r9, rINST, lsr #8           @ r9<- A+
3669    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3670    flds    s0, [r3]                    @ s0<- vB
3671    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3672    and     r9, r9, #15                 @ r9<- A
3673    fsitos  s1, s0                              @ s1<- op
3674    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3675    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3676    fsts    s1, [r9]                    @ vA<- s1
3677    GOTO_OPCODE(ip)                     @ jump to next instruction
3678
3679
3680/* ------------------------------ */
3681    .balign 64
3682.L_OP_INT_TO_DOUBLE: /* 0x83 */
3683/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3684/* File: arm-vfp/funopWider.S */
3685    /*
3686     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3687     * "instr" line that specifies an instruction that performs "d0 = op s0".
3688     *
3689     * For: int-to-double, float-to-double
3690     */
3691    /* unop vA, vB */
3692    mov     r3, rINST, lsr #12          @ r3<- B
3693    mov     r9, rINST, lsr #8           @ r9<- A+
3694    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3695    flds    s0, [r3]                    @ s0<- vB
3696    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3697    and     r9, r9, #15                 @ r9<- A
3698    fsitod  d0, s0                              @ d0<- op
3699    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3700    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3701    fstd    d0, [r9]                    @ vA<- d0
3702    GOTO_OPCODE(ip)                     @ jump to next instruction
3703
3704
3705/* ------------------------------ */
3706    .balign 64
3707.L_OP_LONG_TO_INT: /* 0x84 */
3708/* File: armv5te/OP_LONG_TO_INT.S */
3709/* we ignore the high word, making this equivalent to a 32-bit reg move */
3710/* File: armv5te/OP_MOVE.S */
3711    /* for move, move-object, long-to-int */
3712    /* op vA, vB */
3713    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3714    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3715    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3716    GET_VREG(r2, r1)                    @ r2<- fp[B]
3717    and     r0, r0, #15
3718    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3719    SET_VREG(r2, r0)                    @ fp[A]<- r2
3720    GOTO_OPCODE(ip)                     @ execute next instruction
3721
3722
3723/* ------------------------------ */
3724    .balign 64
3725.L_OP_LONG_TO_FLOAT: /* 0x85 */
3726/* File: armv5te/OP_LONG_TO_FLOAT.S */
3727/* File: armv5te/unopNarrower.S */
3728    /*
3729     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3730     * that specifies an instruction that performs "result = op r0/r1", where
3731     * "result" is a 32-bit quantity in r0.
3732     *
3733     * For: long-to-float, double-to-int, double-to-float
3734     *
3735     * (This would work for long-to-int, but that instruction is actually
3736     * an exact match for OP_MOVE.)
3737     */
3738    /* unop vA, vB */
3739    mov     r3, rINST, lsr #12          @ r3<- B
3740    mov     r9, rINST, lsr #8           @ r9<- A+
3741    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3742    and     r9, r9, #15
3743    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3744    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3745                               @ optional op; may set condition codes
3746    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3748    SET_VREG(r0, r9)                    @ vA<- r0
3749    GOTO_OPCODE(ip)                     @ jump to next instruction
3750    /* 10-11 instructions */
3751
3752
3753/* ------------------------------ */
3754    .balign 64
3755.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3756/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3757/* File: armv5te/unopWide.S */
3758    /*
3759     * Generic 64-bit unary operation.  Provide an "instr" line that
3760     * specifies an instruction that performs "result = op r0/r1".
3761     * This could be an ARM instruction or a function call.
3762     *
3763     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3764     */
3765    /* unop vA, vB */
3766    mov     r9, rINST, lsr #8           @ r9<- A+
3767    mov     r3, rINST, lsr #12          @ r3<- B
3768    and     r9, r9, #15
3769    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3770    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3771    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3772    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3773                               @ optional op; may set condition codes
3774    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3776    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3777    GOTO_OPCODE(ip)                     @ jump to next instruction
3778    /* 12-13 instructions */
3779
3780
3781/* ------------------------------ */
3782    .balign 64
3783.L_OP_FLOAT_TO_INT: /* 0x87 */
3784/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3785/* File: arm-vfp/funop.S */
3786    /*
3787     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3788     * line that specifies an instruction that performs "s1 = op s0".
3789     *
3790     * for: int-to-float, float-to-int
3791     */
3792    /* unop vA, vB */
3793    mov     r3, rINST, lsr #12          @ r3<- B
3794    mov     r9, rINST, lsr #8           @ r9<- A+
3795    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3796    flds    s0, [r3]                    @ s0<- vB
3797    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3798    and     r9, r9, #15                 @ r9<- A
3799    ftosizs s1, s0                              @ s1<- op
3800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3801    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3802    fsts    s1, [r9]                    @ vA<- s1
3803    GOTO_OPCODE(ip)                     @ jump to next instruction
3804
3805
3806/* ------------------------------ */
3807    .balign 64
3808.L_OP_FLOAT_TO_LONG: /* 0x88 */
3809/* File: armv5te/OP_FLOAT_TO_LONG.S */
3810@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3811/* File: armv5te/unopWider.S */
3812    /*
3813     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3814     * that specifies an instruction that performs "result = op r0", where
3815     * "result" is a 64-bit quantity in r0/r1.
3816     *
3817     * For: int-to-long, int-to-double, float-to-long, float-to-double
3818     */
3819    /* unop vA, vB */
3820    mov     r9, rINST, lsr #8           @ r9<- A+
3821    mov     r3, rINST, lsr #12          @ r3<- B
3822    and     r9, r9, #15
3823    GET_VREG(r0, r3)                    @ r0<- vB
3824    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3825                               @ optional op; may set condition codes
3826    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3827    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3829    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3830    GOTO_OPCODE(ip)                     @ jump to next instruction
3831    /* 10-11 instructions */
3832
3833
3834
3835/* ------------------------------ */
3836    .balign 64
3837.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3838/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3839/* File: arm-vfp/funopWider.S */
3840    /*
3841     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3842     * "instr" line that specifies an instruction that performs "d0 = op s0".
3843     *
3844     * For: int-to-double, float-to-double
3845     */
3846    /* unop vA, vB */
3847    mov     r3, rINST, lsr #12          @ r3<- B
3848    mov     r9, rINST, lsr #8           @ r9<- A+
3849    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3850    flds    s0, [r3]                    @ s0<- vB
3851    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3852    and     r9, r9, #15                 @ r9<- A
3853    fcvtds  d0, s0                              @ d0<- op
3854    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3855    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3856    fstd    d0, [r9]                    @ vA<- d0
3857    GOTO_OPCODE(ip)                     @ jump to next instruction
3858
3859
3860/* ------------------------------ */
3861    .balign 64
3862.L_OP_DOUBLE_TO_INT: /* 0x8a */
3863/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3864/* File: arm-vfp/funopNarrower.S */
3865    /*
3866     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3867     * "instr" line that specifies an instruction that performs "s0 = op d0".
3868     *
3869     * For: double-to-int, double-to-float
3870     */
3871    /* unop vA, vB */
3872    mov     r3, rINST, lsr #12          @ r3<- B
3873    mov     r9, rINST, lsr #8           @ r9<- A+
3874    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3875    fldd    d0, [r3]                    @ d0<- vB
3876    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3877    and     r9, r9, #15                 @ r9<- A
3878    ftosizd  s0, d0                              @ s0<- op
3879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3880    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3881    fsts    s0, [r9]                    @ vA<- s0
3882    GOTO_OPCODE(ip)                     @ jump to next instruction
3883
3884
3885/* ------------------------------ */
3886    .balign 64
3887.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3888/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3889@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3890/* File: armv5te/unopWide.S */
3891    /*
3892     * Generic 64-bit unary operation.  Provide an "instr" line that
3893     * specifies an instruction that performs "result = op r0/r1".
3894     * This could be an ARM instruction or a function call.
3895     *
3896     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3897     */
3898    /* unop vA, vB */
3899    mov     r9, rINST, lsr #8           @ r9<- A+
3900    mov     r3, rINST, lsr #12          @ r3<- B
3901    and     r9, r9, #15
3902    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3903    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3904    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3905    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3906                               @ optional op; may set condition codes
3907    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3909    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3910    GOTO_OPCODE(ip)                     @ jump to next instruction
3911    /* 12-13 instructions */
3912
3913
3914
3915/* ------------------------------ */
3916    .balign 64
3917.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3918/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3919/* File: arm-vfp/funopNarrower.S */
3920    /*
3921     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3922     * "instr" line that specifies an instruction that performs "s0 = op d0".
3923     *
3924     * For: double-to-int, double-to-float
3925     */
3926    /* unop vA, vB */
3927    mov     r3, rINST, lsr #12          @ r3<- B
3928    mov     r9, rINST, lsr #8           @ r9<- A+
3929    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3930    fldd    d0, [r3]                    @ d0<- vB
3931    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3932    and     r9, r9, #15                 @ r9<- A
3933    fcvtsd  s0, d0                              @ s0<- op
3934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3935    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3936    fsts    s0, [r9]                    @ vA<- s0
3937    GOTO_OPCODE(ip)                     @ jump to next instruction
3938
3939
3940/* ------------------------------ */
3941    .balign 64
3942.L_OP_INT_TO_BYTE: /* 0x8d */
3943/* File: armv5te/OP_INT_TO_BYTE.S */
3944/* File: armv5te/unop.S */
3945    /*
3946     * Generic 32-bit unary operation.  Provide an "instr" line that
3947     * specifies an instruction that performs "result = op r0".
3948     * This could be an ARM instruction or a function call.
3949     *
3950     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3951     *      int-to-byte, int-to-char, int-to-short
3952     */
3953    /* unop vA, vB */
3954    mov     r3, rINST, lsr #12          @ r3<- B
3955    mov     r9, rINST, lsr #8           @ r9<- A+
3956    GET_VREG(r0, r3)                    @ r0<- vB
3957    and     r9, r9, #15
3958    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3959    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3960    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3962    SET_VREG(r0, r9)                    @ vAA<- r0
3963    GOTO_OPCODE(ip)                     @ jump to next instruction
3964    /* 9-10 instructions */
3965
3966
3967/* ------------------------------ */
3968    .balign 64
3969.L_OP_INT_TO_CHAR: /* 0x8e */
3970/* File: armv5te/OP_INT_TO_CHAR.S */
3971/* File: armv5te/unop.S */
3972    /*
3973     * Generic 32-bit unary operation.  Provide an "instr" line that
3974     * specifies an instruction that performs "result = op r0".
3975     * This could be an ARM instruction or a function call.
3976     *
3977     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3978     *      int-to-byte, int-to-char, int-to-short
3979     */
3980    /* unop vA, vB */
3981    mov     r3, rINST, lsr #12          @ r3<- B
3982    mov     r9, rINST, lsr #8           @ r9<- A+
3983    GET_VREG(r0, r3)                    @ r0<- vB
3984    and     r9, r9, #15
3985    mov     r0, r0, asl #16                           @ optional op; may set condition codes
3986    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3987    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3989    SET_VREG(r0, r9)                    @ vAA<- r0
3990    GOTO_OPCODE(ip)                     @ jump to next instruction
3991    /* 9-10 instructions */
3992
3993
3994/* ------------------------------ */
3995    .balign 64
3996.L_OP_INT_TO_SHORT: /* 0x8f */
3997/* File: armv5te/OP_INT_TO_SHORT.S */
3998/* File: armv5te/unop.S */
3999    /*
4000     * Generic 32-bit unary operation.  Provide an "instr" line that
4001     * specifies an instruction that performs "result = op r0".
4002     * This could be an ARM instruction or a function call.
4003     *
4004     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005     *      int-to-byte, int-to-char, int-to-short
4006     */
4007    /* unop vA, vB */
4008    mov     r3, rINST, lsr #12          @ r3<- B
4009    mov     r9, rINST, lsr #8           @ r9<- A+
4010    GET_VREG(r0, r3)                    @ r0<- vB
4011    and     r9, r9, #15
4012    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4013    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4014    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4015    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4016    SET_VREG(r0, r9)                    @ vAA<- r0
4017    GOTO_OPCODE(ip)                     @ jump to next instruction
4018    /* 9-10 instructions */
4019
4020
4021/* ------------------------------ */
4022    .balign 64
4023.L_OP_ADD_INT: /* 0x90 */
4024/* File: armv5te/OP_ADD_INT.S */
4025/* File: armv5te/binop.S */
4026    /*
4027     * Generic 32-bit binary operation.  Provide an "instr" line that
4028     * specifies an instruction that performs "result = r0 op r1".
4029     * This could be an ARM instruction or a function call.  (If the result
4030     * comes back in a register other than r0, you can override "result".)
4031     *
4032     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4033     * vCC (r1).  Useful for integer division and modulus.  Note that we
4034     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4035     * handles it correctly.
4036     *
4037     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4038     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4039     *      mul-float, div-float, rem-float
4040     */
4041    /* binop vAA, vBB, vCC */
4042    FETCH(r0, 1)                        @ r0<- CCBB
4043    mov     r9, rINST, lsr #8           @ r9<- AA
4044    mov     r3, r0, lsr #8              @ r3<- CC
4045    and     r2, r0, #255                @ r2<- BB
4046    GET_VREG(r1, r3)                    @ r1<- vCC
4047    GET_VREG(r0, r2)                    @ r0<- vBB
4048    .if 0
4049    cmp     r1, #0                      @ is second operand zero?
4050    beq     common_errDivideByZero
4051    .endif
4052
4053    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4054                               @ optional op; may set condition codes
4055    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4056    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4057    SET_VREG(r0, r9)               @ vAA<- r0
4058    GOTO_OPCODE(ip)                     @ jump to next instruction
4059    /* 11-14 instructions */
4060
4061
4062/* ------------------------------ */
4063    .balign 64
4064.L_OP_SUB_INT: /* 0x91 */
4065/* File: armv5te/OP_SUB_INT.S */
4066/* File: armv5te/binop.S */
4067    /*
4068     * Generic 32-bit binary operation.  Provide an "instr" line that
4069     * specifies an instruction that performs "result = r0 op r1".
4070     * This could be an ARM instruction or a function call.  (If the result
4071     * comes back in a register other than r0, you can override "result".)
4072     *
4073     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4074     * vCC (r1).  Useful for integer division and modulus.  Note that we
4075     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4076     * handles it correctly.
4077     *
4078     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4079     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4080     *      mul-float, div-float, rem-float
4081     */
4082    /* binop vAA, vBB, vCC */
4083    FETCH(r0, 1)                        @ r0<- CCBB
4084    mov     r9, rINST, lsr #8           @ r9<- AA
4085    mov     r3, r0, lsr #8              @ r3<- CC
4086    and     r2, r0, #255                @ r2<- BB
4087    GET_VREG(r1, r3)                    @ r1<- vCC
4088    GET_VREG(r0, r2)                    @ r0<- vBB
4089    .if 0
4090    cmp     r1, #0                      @ is second operand zero?
4091    beq     common_errDivideByZero
4092    .endif
4093
4094    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4095                               @ optional op; may set condition codes
4096    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4098    SET_VREG(r0, r9)               @ vAA<- r0
4099    GOTO_OPCODE(ip)                     @ jump to next instruction
4100    /* 11-14 instructions */
4101
4102
4103/* ------------------------------ */
4104    .balign 64
4105.L_OP_MUL_INT: /* 0x92 */
4106/* File: armv5te/OP_MUL_INT.S */
4107/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4108/* File: armv5te/binop.S */
4109    /*
4110     * Generic 32-bit binary operation.  Provide an "instr" line that
4111     * specifies an instruction that performs "result = r0 op r1".
4112     * This could be an ARM instruction or a function call.  (If the result
4113     * comes back in a register other than r0, you can override "result".)
4114     *
4115     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4116     * vCC (r1).  Useful for integer division and modulus.  Note that we
4117     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4118     * handles it correctly.
4119     *
4120     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4121     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4122     *      mul-float, div-float, rem-float
4123     */
4124    /* binop vAA, vBB, vCC */
4125    FETCH(r0, 1)                        @ r0<- CCBB
4126    mov     r9, rINST, lsr #8           @ r9<- AA
4127    mov     r3, r0, lsr #8              @ r3<- CC
4128    and     r2, r0, #255                @ r2<- BB
4129    GET_VREG(r1, r3)                    @ r1<- vCC
4130    GET_VREG(r0, r2)                    @ r0<- vBB
4131    .if 0
4132    cmp     r1, #0                      @ is second operand zero?
4133    beq     common_errDivideByZero
4134    .endif
4135
4136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4137                               @ optional op; may set condition codes
4138    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4139    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4140    SET_VREG(r0, r9)               @ vAA<- r0
4141    GOTO_OPCODE(ip)                     @ jump to next instruction
4142    /* 11-14 instructions */
4143
4144
4145/* ------------------------------ */
4146    .balign 64
4147.L_OP_DIV_INT: /* 0x93 */
4148/* File: armv5te/OP_DIV_INT.S */
4149/* File: armv5te/binop.S */
4150    /*
4151     * Generic 32-bit binary operation.  Provide an "instr" line that
4152     * specifies an instruction that performs "result = r0 op r1".
4153     * This could be an ARM instruction or a function call.  (If the result
4154     * comes back in a register other than r0, you can override "result".)
4155     *
4156     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4157     * vCC (r1).  Useful for integer division and modulus.  Note that we
4158     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4159     * handles it correctly.
4160     *
4161     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4162     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4163     *      mul-float, div-float, rem-float
4164     */
4165    /* binop vAA, vBB, vCC */
4166    FETCH(r0, 1)                        @ r0<- CCBB
4167    mov     r9, rINST, lsr #8           @ r9<- AA
4168    mov     r3, r0, lsr #8              @ r3<- CC
4169    and     r2, r0, #255                @ r2<- BB
4170    GET_VREG(r1, r3)                    @ r1<- vCC
4171    GET_VREG(r0, r2)                    @ r0<- vBB
4172    .if 1
4173    cmp     r1, #0                      @ is second operand zero?
4174    beq     common_errDivideByZero
4175    .endif
4176
4177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4178                               @ optional op; may set condition codes
4179    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4181    SET_VREG(r0, r9)               @ vAA<- r0
4182    GOTO_OPCODE(ip)                     @ jump to next instruction
4183    /* 11-14 instructions */
4184
4185
4186/* ------------------------------ */
4187    .balign 64
4188.L_OP_REM_INT: /* 0x94 */
4189/* File: armv5te/OP_REM_INT.S */
4190/* idivmod returns quotient in r0 and remainder in r1 */
4191/* File: armv5te/binop.S */
4192    /*
4193     * Generic 32-bit binary operation.  Provide an "instr" line that
4194     * specifies an instruction that performs "result = r0 op r1".
4195     * This could be an ARM instruction or a function call.  (If the result
4196     * comes back in a register other than r0, you can override "result".)
4197     *
4198     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4199     * vCC (r1).  Useful for integer division and modulus.  Note that we
4200     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4201     * handles it correctly.
4202     *
4203     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4204     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4205     *      mul-float, div-float, rem-float
4206     */
4207    /* binop vAA, vBB, vCC */
4208    FETCH(r0, 1)                        @ r0<- CCBB
4209    mov     r9, rINST, lsr #8           @ r9<- AA
4210    mov     r3, r0, lsr #8              @ r3<- CC
4211    and     r2, r0, #255                @ r2<- BB
4212    GET_VREG(r1, r3)                    @ r1<- vCC
4213    GET_VREG(r0, r2)                    @ r0<- vBB
4214    .if 1
4215    cmp     r1, #0                      @ is second operand zero?
4216    beq     common_errDivideByZero
4217    .endif
4218
4219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4220                               @ optional op; may set condition codes
4221    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4223    SET_VREG(r1, r9)               @ vAA<- r1
4224    GOTO_OPCODE(ip)                     @ jump to next instruction
4225    /* 11-14 instructions */
4226
4227
4228/* ------------------------------ */
4229    .balign 64
4230.L_OP_AND_INT: /* 0x95 */
4231/* File: armv5te/OP_AND_INT.S */
4232/* File: armv5te/binop.S */
4233    /*
4234     * Generic 32-bit binary operation.  Provide an "instr" line that
4235     * specifies an instruction that performs "result = r0 op r1".
4236     * This could be an ARM instruction or a function call.  (If the result
4237     * comes back in a register other than r0, you can override "result".)
4238     *
4239     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4240     * vCC (r1).  Useful for integer division and modulus.  Note that we
4241     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4242     * handles it correctly.
4243     *
4244     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4245     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4246     *      mul-float, div-float, rem-float
4247     */
4248    /* binop vAA, vBB, vCC */
4249    FETCH(r0, 1)                        @ r0<- CCBB
4250    mov     r9, rINST, lsr #8           @ r9<- AA
4251    mov     r3, r0, lsr #8              @ r3<- CC
4252    and     r2, r0, #255                @ r2<- BB
4253    GET_VREG(r1, r3)                    @ r1<- vCC
4254    GET_VREG(r0, r2)                    @ r0<- vBB
4255    .if 0
4256    cmp     r1, #0                      @ is second operand zero?
4257    beq     common_errDivideByZero
4258    .endif
4259
4260    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4261                               @ optional op; may set condition codes
4262    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4264    SET_VREG(r0, r9)               @ vAA<- r0
4265    GOTO_OPCODE(ip)                     @ jump to next instruction
4266    /* 11-14 instructions */
4267
4268
4269/* ------------------------------ */
4270    .balign 64
4271.L_OP_OR_INT: /* 0x96 */
4272/* File: armv5te/OP_OR_INT.S */
4273/* File: armv5te/binop.S */
4274    /*
4275     * Generic 32-bit binary operation.  Provide an "instr" line that
4276     * specifies an instruction that performs "result = r0 op r1".
4277     * This could be an ARM instruction or a function call.  (If the result
4278     * comes back in a register other than r0, you can override "result".)
4279     *
4280     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4281     * vCC (r1).  Useful for integer division and modulus.  Note that we
4282     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4283     * handles it correctly.
4284     *
4285     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4286     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4287     *      mul-float, div-float, rem-float
4288     */
4289    /* binop vAA, vBB, vCC */
4290    FETCH(r0, 1)                        @ r0<- CCBB
4291    mov     r9, rINST, lsr #8           @ r9<- AA
4292    mov     r3, r0, lsr #8              @ r3<- CC
4293    and     r2, r0, #255                @ r2<- BB
4294    GET_VREG(r1, r3)                    @ r1<- vCC
4295    GET_VREG(r0, r2)                    @ r0<- vBB
4296    .if 0
4297    cmp     r1, #0                      @ is second operand zero?
4298    beq     common_errDivideByZero
4299    .endif
4300
4301    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4302                               @ optional op; may set condition codes
4303    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4305    SET_VREG(r0, r9)               @ vAA<- r0
4306    GOTO_OPCODE(ip)                     @ jump to next instruction
4307    /* 11-14 instructions */
4308
4309
4310/* ------------------------------ */
4311    .balign 64
4312.L_OP_XOR_INT: /* 0x97 */
4313/* File: armv5te/OP_XOR_INT.S */
4314/* File: armv5te/binop.S */
4315    /*
4316     * Generic 32-bit binary operation.  Provide an "instr" line that
4317     * specifies an instruction that performs "result = r0 op r1".
4318     * This could be an ARM instruction or a function call.  (If the result
4319     * comes back in a register other than r0, you can override "result".)
4320     *
4321     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4322     * vCC (r1).  Useful for integer division and modulus.  Note that we
4323     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4324     * handles it correctly.
4325     *
4326     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4327     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4328     *      mul-float, div-float, rem-float
4329     */
4330    /* binop vAA, vBB, vCC */
4331    FETCH(r0, 1)                        @ r0<- CCBB
4332    mov     r9, rINST, lsr #8           @ r9<- AA
4333    mov     r3, r0, lsr #8              @ r3<- CC
4334    and     r2, r0, #255                @ r2<- BB
4335    GET_VREG(r1, r3)                    @ r1<- vCC
4336    GET_VREG(r0, r2)                    @ r0<- vBB
4337    .if 0
4338    cmp     r1, #0                      @ is second operand zero?
4339    beq     common_errDivideByZero
4340    .endif
4341
4342    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4343                               @ optional op; may set condition codes
4344    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4346    SET_VREG(r0, r9)               @ vAA<- r0
4347    GOTO_OPCODE(ip)                     @ jump to next instruction
4348    /* 11-14 instructions */
4349
4350
4351/* ------------------------------ */
4352    .balign 64
4353.L_OP_SHL_INT: /* 0x98 */
4354/* File: armv5te/OP_SHL_INT.S */
4355/* File: armv5te/binop.S */
4356    /*
4357     * Generic 32-bit binary operation.  Provide an "instr" line that
4358     * specifies an instruction that performs "result = r0 op r1".
4359     * This could be an ARM instruction or a function call.  (If the result
4360     * comes back in a register other than r0, you can override "result".)
4361     *
4362     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4363     * vCC (r1).  Useful for integer division and modulus.  Note that we
4364     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4365     * handles it correctly.
4366     *
4367     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4368     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4369     *      mul-float, div-float, rem-float
4370     */
4371    /* binop vAA, vBB, vCC */
4372    FETCH(r0, 1)                        @ r0<- CCBB
4373    mov     r9, rINST, lsr #8           @ r9<- AA
4374    mov     r3, r0, lsr #8              @ r3<- CC
4375    and     r2, r0, #255                @ r2<- BB
4376    GET_VREG(r1, r3)                    @ r1<- vCC
4377    GET_VREG(r0, r2)                    @ r0<- vBB
4378    .if 0
4379    cmp     r1, #0                      @ is second operand zero?
4380    beq     common_errDivideByZero
4381    .endif
4382
4383    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4384    and     r1, r1, #31                           @ optional op; may set condition codes
4385    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4387    SET_VREG(r0, r9)               @ vAA<- r0
4388    GOTO_OPCODE(ip)                     @ jump to next instruction
4389    /* 11-14 instructions */
4390
4391
4392/* ------------------------------ */
4393    .balign 64
4394.L_OP_SHR_INT: /* 0x99 */
4395/* File: armv5te/OP_SHR_INT.S */
4396/* File: armv5te/binop.S */
4397    /*
4398     * Generic 32-bit binary operation.  Provide an "instr" line that
4399     * specifies an instruction that performs "result = r0 op r1".
4400     * This could be an ARM instruction or a function call.  (If the result
4401     * comes back in a register other than r0, you can override "result".)
4402     *
4403     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4404     * vCC (r1).  Useful for integer division and modulus.  Note that we
4405     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4406     * handles it correctly.
4407     *
4408     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4409     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4410     *      mul-float, div-float, rem-float
4411     */
4412    /* binop vAA, vBB, vCC */
4413    FETCH(r0, 1)                        @ r0<- CCBB
4414    mov     r9, rINST, lsr #8           @ r9<- AA
4415    mov     r3, r0, lsr #8              @ r3<- CC
4416    and     r2, r0, #255                @ r2<- BB
4417    GET_VREG(r1, r3)                    @ r1<- vCC
4418    GET_VREG(r0, r2)                    @ r0<- vBB
4419    .if 0
4420    cmp     r1, #0                      @ is second operand zero?
4421    beq     common_errDivideByZero
4422    .endif
4423
4424    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4425    and     r1, r1, #31                           @ optional op; may set condition codes
4426    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4428    SET_VREG(r0, r9)               @ vAA<- r0
4429    GOTO_OPCODE(ip)                     @ jump to next instruction
4430    /* 11-14 instructions */
4431
4432
4433/* ------------------------------ */
4434    .balign 64
4435.L_OP_USHR_INT: /* 0x9a */
4436/* File: armv5te/OP_USHR_INT.S */
4437/* File: armv5te/binop.S */
4438    /*
4439     * Generic 32-bit binary operation.  Provide an "instr" line that
4440     * specifies an instruction that performs "result = r0 op r1".
4441     * This could be an ARM instruction or a function call.  (If the result
4442     * comes back in a register other than r0, you can override "result".)
4443     *
4444     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4445     * vCC (r1).  Useful for integer division and modulus.  Note that we
4446     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4447     * handles it correctly.
4448     *
4449     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4450     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4451     *      mul-float, div-float, rem-float
4452     */
4453    /* binop vAA, vBB, vCC */
4454    FETCH(r0, 1)                        @ r0<- CCBB
4455    mov     r9, rINST, lsr #8           @ r9<- AA
4456    mov     r3, r0, lsr #8              @ r3<- CC
4457    and     r2, r0, #255                @ r2<- BB
4458    GET_VREG(r1, r3)                    @ r1<- vCC
4459    GET_VREG(r0, r2)                    @ r0<- vBB
4460    .if 0
4461    cmp     r1, #0                      @ is second operand zero?
4462    beq     common_errDivideByZero
4463    .endif
4464
4465    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4466    and     r1, r1, #31                           @ optional op; may set condition codes
4467    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4469    SET_VREG(r0, r9)               @ vAA<- r0
4470    GOTO_OPCODE(ip)                     @ jump to next instruction
4471    /* 11-14 instructions */
4472
4473
4474/* ------------------------------ */
4475    .balign 64
4476.L_OP_ADD_LONG: /* 0x9b */
4477/* File: armv5te/OP_ADD_LONG.S */
4478/* File: armv5te/binopWide.S */
4479    /*
4480     * Generic 64-bit binary operation.  Provide an "instr" line that
4481     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4482     * This could be an ARM instruction or a function call.  (If the result
4483     * comes back in a register other than r0, you can override "result".)
4484     *
4485     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4486     * vCC (r1).  Useful for integer division and modulus.
4487     *
4488     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4489     *      xor-long, add-double, sub-double, mul-double, div-double,
4490     *      rem-double
4491     *
4492     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4493     */
4494    /* binop vAA, vBB, vCC */
4495    FETCH(r0, 1)                        @ r0<- CCBB
4496    mov     r9, rINST, lsr #8           @ r9<- AA
4497    and     r2, r0, #255                @ r2<- BB
4498    mov     r3, r0, lsr #8              @ r3<- CC
4499    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4500    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4501    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4502    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4503    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4504    .if 0
4505    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4506    beq     common_errDivideByZero
4507    .endif
4508    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4509
4510    adds    r0, r0, r2                           @ optional op; may set condition codes
4511    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4513    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4514    GOTO_OPCODE(ip)                     @ jump to next instruction
4515    /* 14-17 instructions */
4516
4517
4518/* ------------------------------ */
4519    .balign 64
4520.L_OP_SUB_LONG: /* 0x9c */
4521/* File: armv5te/OP_SUB_LONG.S */
4522/* File: armv5te/binopWide.S */
4523    /*
4524     * Generic 64-bit binary operation.  Provide an "instr" line that
4525     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4526     * This could be an ARM instruction or a function call.  (If the result
4527     * comes back in a register other than r0, you can override "result".)
4528     *
4529     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4530     * vCC (r1).  Useful for integer division and modulus.
4531     *
4532     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4533     *      xor-long, add-double, sub-double, mul-double, div-double,
4534     *      rem-double
4535     *
4536     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4537     */
4538    /* binop vAA, vBB, vCC */
4539    FETCH(r0, 1)                        @ r0<- CCBB
4540    mov     r9, rINST, lsr #8           @ r9<- AA
4541    and     r2, r0, #255                @ r2<- BB
4542    mov     r3, r0, lsr #8              @ r3<- CC
4543    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4544    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4545    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4546    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4547    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4548    .if 0
4549    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4550    beq     common_errDivideByZero
4551    .endif
4552    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4553
4554    subs    r0, r0, r2                           @ optional op; may set condition codes
4555    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4556    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4557    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4558    GOTO_OPCODE(ip)                     @ jump to next instruction
4559    /* 14-17 instructions */
4560
4561
4562/* ------------------------------ */
4563    .balign 64
4564.L_OP_MUL_LONG: /* 0x9d */
4565/* File: armv5te/OP_MUL_LONG.S */
4566    /*
4567     * Signed 64-bit integer multiply.
4568     *
4569     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4570     *        WX
4571     *      x YZ
4572     *  --------
4573     *     ZW ZX
4574     *  YW YX
4575     *
4576     * The low word of the result holds ZX, the high word holds
4577     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4578     * it doesn't fit in the low 64 bits.
4579     *
4580     * Unlike most ARM math operations, multiply instructions have
4581     * restrictions on using the same register more than once (Rd and Rm
4582     * cannot be the same).
4583     */
4584    /* mul-long vAA, vBB, vCC */
4585    FETCH(r0, 1)                        @ r0<- CCBB
4586    and     r2, r0, #255                @ r2<- BB
4587    mov     r3, r0, lsr #8              @ r3<- CC
4588    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4589    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4590    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4591    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4592    mul     ip, r2, r1                  @  ip<- ZxW
4593    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4594    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4595    mov     r0, rINST, lsr #8           @ r0<- AA
4596    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4597    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4598    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4599    b       .LOP_MUL_LONG_finish
4600
4601/* ------------------------------ */
4602    .balign 64
4603.L_OP_DIV_LONG: /* 0x9e */
4604/* File: armv5te/OP_DIV_LONG.S */
4605/* File: armv5te/binopWide.S */
4606    /*
4607     * Generic 64-bit binary operation.  Provide an "instr" line that
4608     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4609     * This could be an ARM instruction or a function call.  (If the result
4610     * comes back in a register other than r0, you can override "result".)
4611     *
4612     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4613     * vCC (r1).  Useful for integer division and modulus.
4614     *
4615     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4616     *      xor-long, add-double, sub-double, mul-double, div-double,
4617     *      rem-double
4618     *
4619     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4620     */
4621    /* binop vAA, vBB, vCC */
4622    FETCH(r0, 1)                        @ r0<- CCBB
4623    mov     r9, rINST, lsr #8           @ r9<- AA
4624    and     r2, r0, #255                @ r2<- BB
4625    mov     r3, r0, lsr #8              @ r3<- CC
4626    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4627    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4628    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4629    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4630    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4631    .if 1
4632    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4633    beq     common_errDivideByZero
4634    .endif
4635    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4636
4637                               @ optional op; may set condition codes
4638    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4639    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4640    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4641    GOTO_OPCODE(ip)                     @ jump to next instruction
4642    /* 14-17 instructions */
4643
4644
4645/* ------------------------------ */
4646    .balign 64
4647.L_OP_REM_LONG: /* 0x9f */
4648/* File: armv5te/OP_REM_LONG.S */
4649/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4650/* File: armv5te/binopWide.S */
4651    /*
4652     * Generic 64-bit binary operation.  Provide an "instr" line that
4653     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4654     * This could be an ARM instruction or a function call.  (If the result
4655     * comes back in a register other than r0, you can override "result".)
4656     *
4657     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4658     * vCC (r1).  Useful for integer division and modulus.
4659     *
4660     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4661     *      xor-long, add-double, sub-double, mul-double, div-double,
4662     *      rem-double
4663     *
4664     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4665     */
4666    /* binop vAA, vBB, vCC */
4667    FETCH(r0, 1)                        @ r0<- CCBB
4668    mov     r9, rINST, lsr #8           @ r9<- AA
4669    and     r2, r0, #255                @ r2<- BB
4670    mov     r3, r0, lsr #8              @ r3<- CC
4671    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4672    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4673    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4674    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4675    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4676    .if 1
4677    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4678    beq     common_errDivideByZero
4679    .endif
4680    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4681
4682                               @ optional op; may set condition codes
4683    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4685    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4686    GOTO_OPCODE(ip)                     @ jump to next instruction
4687    /* 14-17 instructions */
4688
4689
4690/* ------------------------------ */
4691    .balign 64
4692.L_OP_AND_LONG: /* 0xa0 */
4693/* File: armv5te/OP_AND_LONG.S */
4694/* File: armv5te/binopWide.S */
4695    /*
4696     * Generic 64-bit binary operation.  Provide an "instr" line that
4697     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4698     * This could be an ARM instruction or a function call.  (If the result
4699     * comes back in a register other than r0, you can override "result".)
4700     *
4701     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4702     * vCC (r1).  Useful for integer division and modulus.
4703     *
4704     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4705     *      xor-long, add-double, sub-double, mul-double, div-double,
4706     *      rem-double
4707     *
4708     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4709     */
4710    /* binop vAA, vBB, vCC */
4711    FETCH(r0, 1)                        @ r0<- CCBB
4712    mov     r9, rINST, lsr #8           @ r9<- AA
4713    and     r2, r0, #255                @ r2<- BB
4714    mov     r3, r0, lsr #8              @ r3<- CC
4715    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4716    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4717    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4718    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4719    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4720    .if 0
4721    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4722    beq     common_errDivideByZero
4723    .endif
4724    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4725
4726    and     r0, r0, r2                           @ optional op; may set condition codes
4727    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4729    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4730    GOTO_OPCODE(ip)                     @ jump to next instruction
4731    /* 14-17 instructions */
4732
4733
4734/* ------------------------------ */
4735    .balign 64
4736.L_OP_OR_LONG: /* 0xa1 */
4737/* File: armv5te/OP_OR_LONG.S */
4738/* File: armv5te/binopWide.S */
4739    /*
4740     * Generic 64-bit binary operation.  Provide an "instr" line that
4741     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4742     * This could be an ARM instruction or a function call.  (If the result
4743     * comes back in a register other than r0, you can override "result".)
4744     *
4745     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4746     * vCC (r1).  Useful for integer division and modulus.
4747     *
4748     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4749     *      xor-long, add-double, sub-double, mul-double, div-double,
4750     *      rem-double
4751     *
4752     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4753     */
4754    /* binop vAA, vBB, vCC */
4755    FETCH(r0, 1)                        @ r0<- CCBB
4756    mov     r9, rINST, lsr #8           @ r9<- AA
4757    and     r2, r0, #255                @ r2<- BB
4758    mov     r3, r0, lsr #8              @ r3<- CC
4759    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4760    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4761    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4762    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4763    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4764    .if 0
4765    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4766    beq     common_errDivideByZero
4767    .endif
4768    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4769
4770    orr     r0, r0, r2                           @ optional op; may set condition codes
4771    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4772    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4773    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4774    GOTO_OPCODE(ip)                     @ jump to next instruction
4775    /* 14-17 instructions */
4776
4777
4778/* ------------------------------ */
4779    .balign 64
4780.L_OP_XOR_LONG: /* 0xa2 */
4781/* File: armv5te/OP_XOR_LONG.S */
4782/* File: armv5te/binopWide.S */
4783    /*
4784     * Generic 64-bit binary operation.  Provide an "instr" line that
4785     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4786     * This could be an ARM instruction or a function call.  (If the result
4787     * comes back in a register other than r0, you can override "result".)
4788     *
4789     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4790     * vCC (r1).  Useful for integer division and modulus.
4791     *
4792     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4793     *      xor-long, add-double, sub-double, mul-double, div-double,
4794     *      rem-double
4795     *
4796     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4797     */
4798    /* binop vAA, vBB, vCC */
4799    FETCH(r0, 1)                        @ r0<- CCBB
4800    mov     r9, rINST, lsr #8           @ r9<- AA
4801    and     r2, r0, #255                @ r2<- BB
4802    mov     r3, r0, lsr #8              @ r3<- CC
4803    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4804    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4805    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4806    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4807    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4808    .if 0
4809    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4810    beq     common_errDivideByZero
4811    .endif
4812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4813
4814    eor     r0, r0, r2                           @ optional op; may set condition codes
4815    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4817    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4818    GOTO_OPCODE(ip)                     @ jump to next instruction
4819    /* 14-17 instructions */
4820
4821
4822/* ------------------------------ */
4823    .balign 64
4824.L_OP_SHL_LONG: /* 0xa3 */
4825/* File: armv5te/OP_SHL_LONG.S */
4826    /*
4827     * Long integer shift.  This is different from the generic 32/64-bit
4828     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4829     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4830     * 6 bits of the shift distance.
4831     */
4832    /* shl-long vAA, vBB, vCC */
4833    FETCH(r0, 1)                        @ r0<- CCBB
4834    mov     r9, rINST, lsr #8           @ r9<- AA
4835    and     r3, r0, #255                @ r3<- BB
4836    mov     r0, r0, lsr #8              @ r0<- CC
4837    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4838    GET_VREG(r2, r0)                    @ r2<- vCC
4839    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4840    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4841    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4842
4843    mov     r1, r1, asl r2              @  r1<- r1 << r2
4844    rsb     r3, r2, #32                 @  r3<- 32 - r2
4845    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4846    subs    ip, r2, #32                 @  ip<- r2 - 32
4847    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4848    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4849    b       .LOP_SHL_LONG_finish
4850
4851/* ------------------------------ */
4852    .balign 64
4853.L_OP_SHR_LONG: /* 0xa4 */
4854/* File: armv5te/OP_SHR_LONG.S */
4855    /*
4856     * Long integer shift.  This is different from the generic 32/64-bit
4857     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4858     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4859     * 6 bits of the shift distance.
4860     */
4861    /* shr-long vAA, vBB, vCC */
4862    FETCH(r0, 1)                        @ r0<- CCBB
4863    mov     r9, rINST, lsr #8           @ r9<- AA
4864    and     r3, r0, #255                @ r3<- BB
4865    mov     r0, r0, lsr #8              @ r0<- CC
4866    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4867    GET_VREG(r2, r0)                    @ r2<- vCC
4868    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4869    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4870    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4871
4872    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4873    rsb     r3, r2, #32                 @  r3<- 32 - r2
4874    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4875    subs    ip, r2, #32                 @  ip<- r2 - 32
4876    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4877    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4878    b       .LOP_SHR_LONG_finish
4879
4880/* ------------------------------ */
4881    .balign 64
4882.L_OP_USHR_LONG: /* 0xa5 */
4883/* File: armv5te/OP_USHR_LONG.S */
4884    /*
4885     * Long integer shift.  This is different from the generic 32/64-bit
4886     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4887     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4888     * 6 bits of the shift distance.
4889     */
4890    /* ushr-long vAA, vBB, vCC */
4891    FETCH(r0, 1)                        @ r0<- CCBB
4892    mov     r9, rINST, lsr #8           @ r9<- AA
4893    and     r3, r0, #255                @ r3<- BB
4894    mov     r0, r0, lsr #8              @ r0<- CC
4895    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4896    GET_VREG(r2, r0)                    @ r2<- vCC
4897    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4898    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4900
4901    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4902    rsb     r3, r2, #32                 @  r3<- 32 - r2
4903    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4904    subs    ip, r2, #32                 @  ip<- r2 - 32
4905    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4906    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4907    b       .LOP_USHR_LONG_finish
4908
4909/* ------------------------------ */
4910    .balign 64
4911.L_OP_ADD_FLOAT: /* 0xa6 */
4912/* File: arm-vfp/OP_ADD_FLOAT.S */
4913/* File: arm-vfp/fbinop.S */
4914    /*
4915     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4916     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4917     * use the "softfp" ABI, this must be an instruction, not a function call.
4918     *
4919     * For: add-float, sub-float, mul-float, div-float
4920     */
4921    /* floatop vAA, vBB, vCC */
4922    FETCH(r0, 1)                        @ r0<- CCBB
4923    mov     r9, rINST, lsr #8           @ r9<- AA
4924    mov     r3, r0, lsr #8              @ r3<- CC
4925    and     r2, r0, #255                @ r2<- BB
4926    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4927    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4928    flds    s1, [r3]                    @ s1<- vCC
4929    flds    s0, [r2]                    @ s0<- vBB
4930
4931    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4932    fadds   s2, s0, s1                              @ s2<- op
4933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4934    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4935    fsts    s2, [r9]                    @ vAA<- s2
4936    GOTO_OPCODE(ip)                     @ jump to next instruction
4937
4938
4939/* ------------------------------ */
4940    .balign 64
4941.L_OP_SUB_FLOAT: /* 0xa7 */
4942/* File: arm-vfp/OP_SUB_FLOAT.S */
4943/* File: arm-vfp/fbinop.S */
4944    /*
4945     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4946     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4947     * use the "softfp" ABI, this must be an instruction, not a function call.
4948     *
4949     * For: add-float, sub-float, mul-float, div-float
4950     */
4951    /* floatop vAA, vBB, vCC */
4952    FETCH(r0, 1)                        @ r0<- CCBB
4953    mov     r9, rINST, lsr #8           @ r9<- AA
4954    mov     r3, r0, lsr #8              @ r3<- CC
4955    and     r2, r0, #255                @ r2<- BB
4956    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4957    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4958    flds    s1, [r3]                    @ s1<- vCC
4959    flds    s0, [r2]                    @ s0<- vBB
4960
4961    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4962    fsubs   s2, s0, s1                              @ s2<- op
4963    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4964    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4965    fsts    s2, [r9]                    @ vAA<- s2
4966    GOTO_OPCODE(ip)                     @ jump to next instruction
4967
4968
4969/* ------------------------------ */
4970    .balign 64
4971.L_OP_MUL_FLOAT: /* 0xa8 */
4972/* File: arm-vfp/OP_MUL_FLOAT.S */
4973/* File: arm-vfp/fbinop.S */
4974    /*
4975     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4976     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4977     * use the "softfp" ABI, this must be an instruction, not a function call.
4978     *
4979     * For: add-float, sub-float, mul-float, div-float
4980     */
4981    /* floatop vAA, vBB, vCC */
4982    FETCH(r0, 1)                        @ r0<- CCBB
4983    mov     r9, rINST, lsr #8           @ r9<- AA
4984    mov     r3, r0, lsr #8              @ r3<- CC
4985    and     r2, r0, #255                @ r2<- BB
4986    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4987    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4988    flds    s1, [r3]                    @ s1<- vCC
4989    flds    s0, [r2]                    @ s0<- vBB
4990
4991    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4992    fmuls   s2, s0, s1                              @ s2<- op
4993    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4994    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4995    fsts    s2, [r9]                    @ vAA<- s2
4996    GOTO_OPCODE(ip)                     @ jump to next instruction
4997
4998
4999/* ------------------------------ */
5000    .balign 64
5001.L_OP_DIV_FLOAT: /* 0xa9 */
5002/* File: arm-vfp/OP_DIV_FLOAT.S */
5003/* File: arm-vfp/fbinop.S */
5004    /*
5005     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5006     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5007     * use the "softfp" ABI, this must be an instruction, not a function call.
5008     *
5009     * For: add-float, sub-float, mul-float, div-float
5010     */
5011    /* floatop vAA, vBB, vCC */
5012    FETCH(r0, 1)                        @ r0<- CCBB
5013    mov     r9, rINST, lsr #8           @ r9<- AA
5014    mov     r3, r0, lsr #8              @ r3<- CC
5015    and     r2, r0, #255                @ r2<- BB
5016    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5017    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5018    flds    s1, [r3]                    @ s1<- vCC
5019    flds    s0, [r2]                    @ s0<- vBB
5020
5021    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5022    fdivs   s2, s0, s1                              @ s2<- op
5023    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5024    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5025    fsts    s2, [r9]                    @ vAA<- s2
5026    GOTO_OPCODE(ip)                     @ jump to next instruction
5027
5028
5029/* ------------------------------ */
5030    .balign 64
5031.L_OP_REM_FLOAT: /* 0xaa */
5032/* File: armv5te/OP_REM_FLOAT.S */
5033/* EABI doesn't define a float remainder function, but libm does */
5034/* File: armv5te/binop.S */
5035    /*
5036     * Generic 32-bit binary operation.  Provide an "instr" line that
5037     * specifies an instruction that performs "result = r0 op r1".
5038     * This could be an ARM instruction or a function call.  (If the result
5039     * comes back in a register other than r0, you can override "result".)
5040     *
5041     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5042     * vCC (r1).  Useful for integer division and modulus.  Note that we
5043     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5044     * handles it correctly.
5045     *
5046     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5047     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5048     *      mul-float, div-float, rem-float
5049     */
5050    /* binop vAA, vBB, vCC */
5051    FETCH(r0, 1)                        @ r0<- CCBB
5052    mov     r9, rINST, lsr #8           @ r9<- AA
5053    mov     r3, r0, lsr #8              @ r3<- CC
5054    and     r2, r0, #255                @ r2<- BB
5055    GET_VREG(r1, r3)                    @ r1<- vCC
5056    GET_VREG(r0, r2)                    @ r0<- vBB
5057    .if 0
5058    cmp     r1, #0                      @ is second operand zero?
5059    beq     common_errDivideByZero
5060    .endif
5061
5062    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5063                               @ optional op; may set condition codes
5064    bl      fmodf                              @ r0<- op, r0-r3 changed
5065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5066    SET_VREG(r0, r9)               @ vAA<- r0
5067    GOTO_OPCODE(ip)                     @ jump to next instruction
5068    /* 11-14 instructions */
5069
5070
5071/* ------------------------------ */
5072    .balign 64
5073.L_OP_ADD_DOUBLE: /* 0xab */
5074/* File: arm-vfp/OP_ADD_DOUBLE.S */
5075/* File: arm-vfp/fbinopWide.S */
5076    /*
5077     * Generic 64-bit double-precision floating point binary operation.
5078     * Provide an "instr" line that specifies an instruction that performs
5079     * "d2 = d0 op d1".
5080     *
5081     * for: add-double, sub-double, mul-double, div-double
5082     */
5083    /* doubleop vAA, vBB, vCC */
5084    FETCH(r0, 1)                        @ r0<- CCBB
5085    mov     r9, rINST, lsr #8           @ r9<- AA
5086    mov     r3, r0, lsr #8              @ r3<- CC
5087    and     r2, r0, #255                @ r2<- BB
5088    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5089    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5090    fldd    d1, [r3]                    @ d1<- vCC
5091    fldd    d0, [r2]                    @ d0<- vBB
5092
5093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5094    faddd   d2, d0, d1                              @ s2<- op
5095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5096    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5097    fstd    d2, [r9]                    @ vAA<- d2
5098    GOTO_OPCODE(ip)                     @ jump to next instruction
5099
5100
5101/* ------------------------------ */
5102    .balign 64
5103.L_OP_SUB_DOUBLE: /* 0xac */
5104/* File: arm-vfp/OP_SUB_DOUBLE.S */
5105/* File: arm-vfp/fbinopWide.S */
5106    /*
5107     * Generic 64-bit double-precision floating point binary operation.
5108     * Provide an "instr" line that specifies an instruction that performs
5109     * "d2 = d0 op d1".
5110     *
5111     * for: add-double, sub-double, mul-double, div-double
5112     */
5113    /* doubleop vAA, vBB, vCC */
5114    FETCH(r0, 1)                        @ r0<- CCBB
5115    mov     r9, rINST, lsr #8           @ r9<- AA
5116    mov     r3, r0, lsr #8              @ r3<- CC
5117    and     r2, r0, #255                @ r2<- BB
5118    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5119    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5120    fldd    d1, [r3]                    @ d1<- vCC
5121    fldd    d0, [r2]                    @ d0<- vBB
5122
5123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5124    fsubd   d2, d0, d1                              @ s2<- op
5125    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5126    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5127    fstd    d2, [r9]                    @ vAA<- d2
5128    GOTO_OPCODE(ip)                     @ jump to next instruction
5129
5130
5131/* ------------------------------ */
5132    .balign 64
5133.L_OP_MUL_DOUBLE: /* 0xad */
5134/* File: arm-vfp/OP_MUL_DOUBLE.S */
5135/* File: arm-vfp/fbinopWide.S */
5136    /*
5137     * Generic 64-bit double-precision floating point binary operation.
5138     * Provide an "instr" line that specifies an instruction that performs
5139     * "d2 = d0 op d1".
5140     *
5141     * for: add-double, sub-double, mul-double, div-double
5142     */
5143    /* doubleop vAA, vBB, vCC */
5144    FETCH(r0, 1)                        @ r0<- CCBB
5145    mov     r9, rINST, lsr #8           @ r9<- AA
5146    mov     r3, r0, lsr #8              @ r3<- CC
5147    and     r2, r0, #255                @ r2<- BB
5148    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5149    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5150    fldd    d1, [r3]                    @ d1<- vCC
5151    fldd    d0, [r2]                    @ d0<- vBB
5152
5153    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5154    fmuld   d2, d0, d1                              @ s2<- op
5155    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5156    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5157    fstd    d2, [r9]                    @ vAA<- d2
5158    GOTO_OPCODE(ip)                     @ jump to next instruction
5159
5160
5161/* ------------------------------ */
5162    .balign 64
5163.L_OP_DIV_DOUBLE: /* 0xae */
5164/* File: arm-vfp/OP_DIV_DOUBLE.S */
5165/* File: arm-vfp/fbinopWide.S */
5166    /*
5167     * Generic 64-bit double-precision floating point binary operation.
5168     * Provide an "instr" line that specifies an instruction that performs
5169     * "d2 = d0 op d1".
5170     *
5171     * for: add-double, sub-double, mul-double, div-double
5172     */
5173    /* doubleop vAA, vBB, vCC */
5174    FETCH(r0, 1)                        @ r0<- CCBB
5175    mov     r9, rINST, lsr #8           @ r9<- AA
5176    mov     r3, r0, lsr #8              @ r3<- CC
5177    and     r2, r0, #255                @ r2<- BB
5178    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5179    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5180    fldd    d1, [r3]                    @ d1<- vCC
5181    fldd    d0, [r2]                    @ d0<- vBB
5182
5183    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5184    fdivd   d2, d0, d1                              @ s2<- op
5185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5186    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5187    fstd    d2, [r9]                    @ vAA<- d2
5188    GOTO_OPCODE(ip)                     @ jump to next instruction
5189
5190
5191/* ------------------------------ */
5192    .balign 64
5193.L_OP_REM_DOUBLE: /* 0xaf */
5194/* File: armv5te/OP_REM_DOUBLE.S */
5195/* EABI doesn't define a double remainder function, but libm does */
5196/* File: armv5te/binopWide.S */
5197    /*
5198     * Generic 64-bit binary operation.  Provide an "instr" line that
5199     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5200     * This could be an ARM instruction or a function call.  (If the result
5201     * comes back in a register other than r0, you can override "result".)
5202     *
5203     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5204     * vCC (r1).  Useful for integer division and modulus.
5205     *
5206     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5207     *      xor-long, add-double, sub-double, mul-double, div-double,
5208     *      rem-double
5209     *
5210     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5211     */
5212    /* binop vAA, vBB, vCC */
5213    FETCH(r0, 1)                        @ r0<- CCBB
5214    mov     r9, rINST, lsr #8           @ r9<- AA
5215    and     r2, r0, #255                @ r2<- BB
5216    mov     r3, r0, lsr #8              @ r3<- CC
5217    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5218    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5219    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5220    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5221    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5222    .if 0
5223    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5224    beq     common_errDivideByZero
5225    .endif
5226    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5227
5228                               @ optional op; may set condition codes
5229    bl      fmod                              @ result<- op, r0-r3 changed
5230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5231    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5232    GOTO_OPCODE(ip)                     @ jump to next instruction
5233    /* 14-17 instructions */
5234
5235
5236/* ------------------------------ */
5237    .balign 64
5238.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5239/* File: armv5te/OP_ADD_INT_2ADDR.S */
5240/* File: armv5te/binop2addr.S */
5241    /*
5242     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5243     * that specifies an instruction that performs "result = r0 op r1".
5244     * This could be an ARM instruction or a function call.  (If the result
5245     * comes back in a register other than r0, you can override "result".)
5246     *
5247     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5248     * vCC (r1).  Useful for integer division and modulus.
5249     *
5250     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5251     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5252     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5253     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5254     */
5255    /* binop/2addr vA, vB */
5256    mov     r9, rINST, lsr #8           @ r9<- A+
5257    mov     r3, rINST, lsr #12          @ r3<- B
5258    and     r9, r9, #15
5259    GET_VREG(r1, r3)                    @ r1<- vB
5260    GET_VREG(r0, r9)                    @ r0<- vA
5261    .if 0
5262    cmp     r1, #0                      @ is second operand zero?
5263    beq     common_errDivideByZero
5264    .endif
5265    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5266
5267                               @ optional op; may set condition codes
5268    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5270    SET_VREG(r0, r9)               @ vAA<- r0
5271    GOTO_OPCODE(ip)                     @ jump to next instruction
5272    /* 10-13 instructions */
5273
5274
5275/* ------------------------------ */
5276    .balign 64
5277.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5278/* File: armv5te/OP_SUB_INT_2ADDR.S */
5279/* File: armv5te/binop2addr.S */
5280    /*
5281     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5282     * that specifies an instruction that performs "result = r0 op r1".
5283     * This could be an ARM instruction or a function call.  (If the result
5284     * comes back in a register other than r0, you can override "result".)
5285     *
5286     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5287     * vCC (r1).  Useful for integer division and modulus.
5288     *
5289     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5290     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5291     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5292     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5293     */
5294    /* binop/2addr vA, vB */
5295    mov     r9, rINST, lsr #8           @ r9<- A+
5296    mov     r3, rINST, lsr #12          @ r3<- B
5297    and     r9, r9, #15
5298    GET_VREG(r1, r3)                    @ r1<- vB
5299    GET_VREG(r0, r9)                    @ r0<- vA
5300    .if 0
5301    cmp     r1, #0                      @ is second operand zero?
5302    beq     common_errDivideByZero
5303    .endif
5304    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5305
5306                               @ optional op; may set condition codes
5307    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5309    SET_VREG(r0, r9)               @ vAA<- r0
5310    GOTO_OPCODE(ip)                     @ jump to next instruction
5311    /* 10-13 instructions */
5312
5313
5314/* ------------------------------ */
5315    .balign 64
5316.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5317/* File: armv5te/OP_MUL_INT_2ADDR.S */
5318/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5319/* File: armv5te/binop2addr.S */
5320    /*
5321     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5322     * that specifies an instruction that performs "result = r0 op r1".
5323     * This could be an ARM instruction or a function call.  (If the result
5324     * comes back in a register other than r0, you can override "result".)
5325     *
5326     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5327     * vCC (r1).  Useful for integer division and modulus.
5328     *
5329     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5330     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5331     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5332     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5333     */
5334    /* binop/2addr vA, vB */
5335    mov     r9, rINST, lsr #8           @ r9<- A+
5336    mov     r3, rINST, lsr #12          @ r3<- B
5337    and     r9, r9, #15
5338    GET_VREG(r1, r3)                    @ r1<- vB
5339    GET_VREG(r0, r9)                    @ r0<- vA
5340    .if 0
5341    cmp     r1, #0                      @ is second operand zero?
5342    beq     common_errDivideByZero
5343    .endif
5344    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5345
5346                               @ optional op; may set condition codes
5347    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5349    SET_VREG(r0, r9)               @ vAA<- r0
5350    GOTO_OPCODE(ip)                     @ jump to next instruction
5351    /* 10-13 instructions */
5352
5353
5354/* ------------------------------ */
5355    .balign 64
5356.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5357/* File: armv5te/OP_DIV_INT_2ADDR.S */
5358/* File: armv5te/binop2addr.S */
5359    /*
5360     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5361     * that specifies an instruction that performs "result = r0 op r1".
5362     * This could be an ARM instruction or a function call.  (If the result
5363     * comes back in a register other than r0, you can override "result".)
5364     *
5365     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5366     * vCC (r1).  Useful for integer division and modulus.
5367     *
5368     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5369     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5370     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5371     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5372     */
5373    /* binop/2addr vA, vB */
5374    mov     r9, rINST, lsr #8           @ r9<- A+
5375    mov     r3, rINST, lsr #12          @ r3<- B
5376    and     r9, r9, #15
5377    GET_VREG(r1, r3)                    @ r1<- vB
5378    GET_VREG(r0, r9)                    @ r0<- vA
5379    .if 1
5380    cmp     r1, #0                      @ is second operand zero?
5381    beq     common_errDivideByZero
5382    .endif
5383    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5384
5385                               @ optional op; may set condition codes
5386    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5388    SET_VREG(r0, r9)               @ vAA<- r0
5389    GOTO_OPCODE(ip)                     @ jump to next instruction
5390    /* 10-13 instructions */
5391
5392
5393/* ------------------------------ */
5394    .balign 64
5395.L_OP_REM_INT_2ADDR: /* 0xb4 */
5396/* File: armv5te/OP_REM_INT_2ADDR.S */
5397/* idivmod returns quotient in r0 and remainder in r1 */
5398/* File: armv5te/binop2addr.S */
5399    /*
5400     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5401     * that specifies an instruction that performs "result = r0 op r1".
5402     * This could be an ARM instruction or a function call.  (If the result
5403     * comes back in a register other than r0, you can override "result".)
5404     *
5405     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5406     * vCC (r1).  Useful for integer division and modulus.
5407     *
5408     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5409     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5410     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5411     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5412     */
5413    /* binop/2addr vA, vB */
5414    mov     r9, rINST, lsr #8           @ r9<- A+
5415    mov     r3, rINST, lsr #12          @ r3<- B
5416    and     r9, r9, #15
5417    GET_VREG(r1, r3)                    @ r1<- vB
5418    GET_VREG(r0, r9)                    @ r0<- vA
5419    .if 1
5420    cmp     r1, #0                      @ is second operand zero?
5421    beq     common_errDivideByZero
5422    .endif
5423    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5424
5425                               @ optional op; may set condition codes
5426    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5428    SET_VREG(r1, r9)               @ vAA<- r1
5429    GOTO_OPCODE(ip)                     @ jump to next instruction
5430    /* 10-13 instructions */
5431
5432
5433/* ------------------------------ */
5434    .balign 64
5435.L_OP_AND_INT_2ADDR: /* 0xb5 */
5436/* File: armv5te/OP_AND_INT_2ADDR.S */
5437/* File: armv5te/binop2addr.S */
5438    /*
5439     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5440     * that specifies an instruction that performs "result = r0 op r1".
5441     * This could be an ARM instruction or a function call.  (If the result
5442     * comes back in a register other than r0, you can override "result".)
5443     *
5444     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5445     * vCC (r1).  Useful for integer division and modulus.
5446     *
5447     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5448     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5449     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5450     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5451     */
5452    /* binop/2addr vA, vB */
5453    mov     r9, rINST, lsr #8           @ r9<- A+
5454    mov     r3, rINST, lsr #12          @ r3<- B
5455    and     r9, r9, #15
5456    GET_VREG(r1, r3)                    @ r1<- vB
5457    GET_VREG(r0, r9)                    @ r0<- vA
5458    .if 0
5459    cmp     r1, #0                      @ is second operand zero?
5460    beq     common_errDivideByZero
5461    .endif
5462    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5463
5464                               @ optional op; may set condition codes
5465    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5466    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5467    SET_VREG(r0, r9)               @ vAA<- r0
5468    GOTO_OPCODE(ip)                     @ jump to next instruction
5469    /* 10-13 instructions */
5470
5471
5472/* ------------------------------ */
5473    .balign 64
5474.L_OP_OR_INT_2ADDR: /* 0xb6 */
5475/* File: armv5te/OP_OR_INT_2ADDR.S */
5476/* File: armv5te/binop2addr.S */
5477    /*
5478     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5479     * that specifies an instruction that performs "result = r0 op r1".
5480     * This could be an ARM instruction or a function call.  (If the result
5481     * comes back in a register other than r0, you can override "result".)
5482     *
5483     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5484     * vCC (r1).  Useful for integer division and modulus.
5485     *
5486     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5487     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5488     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5489     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5490     */
5491    /* binop/2addr vA, vB */
5492    mov     r9, rINST, lsr #8           @ r9<- A+
5493    mov     r3, rINST, lsr #12          @ r3<- B
5494    and     r9, r9, #15
5495    GET_VREG(r1, r3)                    @ r1<- vB
5496    GET_VREG(r0, r9)                    @ r0<- vA
5497    .if 0
5498    cmp     r1, #0                      @ is second operand zero?
5499    beq     common_errDivideByZero
5500    .endif
5501    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5502
5503                               @ optional op; may set condition codes
5504    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5506    SET_VREG(r0, r9)               @ vAA<- r0
5507    GOTO_OPCODE(ip)                     @ jump to next instruction
5508    /* 10-13 instructions */
5509
5510
5511/* ------------------------------ */
5512    .balign 64
5513.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5514/* File: armv5te/OP_XOR_INT_2ADDR.S */
5515/* File: armv5te/binop2addr.S */
5516    /*
5517     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5518     * that specifies an instruction that performs "result = r0 op r1".
5519     * This could be an ARM instruction or a function call.  (If the result
5520     * comes back in a register other than r0, you can override "result".)
5521     *
5522     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5523     * vCC (r1).  Useful for integer division and modulus.
5524     *
5525     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5526     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5527     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5528     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5529     */
5530    /* binop/2addr vA, vB */
5531    mov     r9, rINST, lsr #8           @ r9<- A+
5532    mov     r3, rINST, lsr #12          @ r3<- B
5533    and     r9, r9, #15
5534    GET_VREG(r1, r3)                    @ r1<- vB
5535    GET_VREG(r0, r9)                    @ r0<- vA
5536    .if 0
5537    cmp     r1, #0                      @ is second operand zero?
5538    beq     common_errDivideByZero
5539    .endif
5540    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5541
5542                               @ optional op; may set condition codes
5543    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5544    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5545    SET_VREG(r0, r9)               @ vAA<- r0
5546    GOTO_OPCODE(ip)                     @ jump to next instruction
5547    /* 10-13 instructions */
5548
5549
5550/* ------------------------------ */
5551    .balign 64
5552.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5553/* File: armv5te/OP_SHL_INT_2ADDR.S */
5554/* File: armv5te/binop2addr.S */
5555    /*
5556     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5557     * that specifies an instruction that performs "result = r0 op r1".
5558     * This could be an ARM instruction or a function call.  (If the result
5559     * comes back in a register other than r0, you can override "result".)
5560     *
5561     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5562     * vCC (r1).  Useful for integer division and modulus.
5563     *
5564     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5565     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5566     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5567     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5568     */
5569    /* binop/2addr vA, vB */
5570    mov     r9, rINST, lsr #8           @ r9<- A+
5571    mov     r3, rINST, lsr #12          @ r3<- B
5572    and     r9, r9, #15
5573    GET_VREG(r1, r3)                    @ r1<- vB
5574    GET_VREG(r0, r9)                    @ r0<- vA
5575    .if 0
5576    cmp     r1, #0                      @ is second operand zero?
5577    beq     common_errDivideByZero
5578    .endif
5579    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5580
5581    and     r1, r1, #31                           @ optional op; may set condition codes
5582    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5584    SET_VREG(r0, r9)               @ vAA<- r0
5585    GOTO_OPCODE(ip)                     @ jump to next instruction
5586    /* 10-13 instructions */
5587
5588
5589/* ------------------------------ */
5590    .balign 64
5591.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5592/* File: armv5te/OP_SHR_INT_2ADDR.S */
5593/* File: armv5te/binop2addr.S */
5594    /*
5595     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5596     * that specifies an instruction that performs "result = r0 op r1".
5597     * This could be an ARM instruction or a function call.  (If the result
5598     * comes back in a register other than r0, you can override "result".)
5599     *
5600     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5601     * vCC (r1).  Useful for integer division and modulus.
5602     *
5603     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5604     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5605     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5606     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5607     */
5608    /* binop/2addr vA, vB */
5609    mov     r9, rINST, lsr #8           @ r9<- A+
5610    mov     r3, rINST, lsr #12          @ r3<- B
5611    and     r9, r9, #15
5612    GET_VREG(r1, r3)                    @ r1<- vB
5613    GET_VREG(r0, r9)                    @ r0<- vA
5614    .if 0
5615    cmp     r1, #0                      @ is second operand zero?
5616    beq     common_errDivideByZero
5617    .endif
5618    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5619
5620    and     r1, r1, #31                           @ optional op; may set condition codes
5621    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5623    SET_VREG(r0, r9)               @ vAA<- r0
5624    GOTO_OPCODE(ip)                     @ jump to next instruction
5625    /* 10-13 instructions */
5626
5627
5628/* ------------------------------ */
5629    .balign 64
5630.L_OP_USHR_INT_2ADDR: /* 0xba */
5631/* File: armv5te/OP_USHR_INT_2ADDR.S */
5632/* File: armv5te/binop2addr.S */
5633    /*
5634     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5635     * that specifies an instruction that performs "result = r0 op r1".
5636     * This could be an ARM instruction or a function call.  (If the result
5637     * comes back in a register other than r0, you can override "result".)
5638     *
5639     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5640     * vCC (r1).  Useful for integer division and modulus.
5641     *
5642     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5643     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5644     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5645     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5646     */
5647    /* binop/2addr vA, vB */
5648    mov     r9, rINST, lsr #8           @ r9<- A+
5649    mov     r3, rINST, lsr #12          @ r3<- B
5650    and     r9, r9, #15
5651    GET_VREG(r1, r3)                    @ r1<- vB
5652    GET_VREG(r0, r9)                    @ r0<- vA
5653    .if 0
5654    cmp     r1, #0                      @ is second operand zero?
5655    beq     common_errDivideByZero
5656    .endif
5657    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5658
5659    and     r1, r1, #31                           @ optional op; may set condition codes
5660    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5661    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5662    SET_VREG(r0, r9)               @ vAA<- r0
5663    GOTO_OPCODE(ip)                     @ jump to next instruction
5664    /* 10-13 instructions */
5665
5666
5667/* ------------------------------ */
5668    .balign 64
5669.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5670/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5671/* File: armv5te/binopWide2addr.S */
5672    /*
5673     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5674     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5675     * This could be an ARM instruction or a function call.  (If the result
5676     * comes back in a register other than r0, you can override "result".)
5677     *
5678     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5679     * vCC (r1).  Useful for integer division and modulus.
5680     *
5681     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5682     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5683     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5684     *      rem-double/2addr
5685     */
5686    /* binop/2addr vA, vB */
5687    mov     r9, rINST, lsr #8           @ r9<- A+
5688    mov     r1, rINST, lsr #12          @ r1<- B
5689    and     r9, r9, #15
5690    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5691    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5692    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5693    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5694    .if 0
5695    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5696    beq     common_errDivideByZero
5697    .endif
5698    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5699
5700    adds    r0, r0, r2                           @ optional op; may set condition codes
5701    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5702    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5703    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5704    GOTO_OPCODE(ip)                     @ jump to next instruction
5705    /* 12-15 instructions */
5706
5707
5708/* ------------------------------ */
5709    .balign 64
5710.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5711/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5712/* File: armv5te/binopWide2addr.S */
5713    /*
5714     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5715     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5716     * This could be an ARM instruction or a function call.  (If the result
5717     * comes back in a register other than r0, you can override "result".)
5718     *
5719     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5720     * vCC (r1).  Useful for integer division and modulus.
5721     *
5722     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5723     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5724     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5725     *      rem-double/2addr
5726     */
5727    /* binop/2addr vA, vB */
5728    mov     r9, rINST, lsr #8           @ r9<- A+
5729    mov     r1, rINST, lsr #12          @ r1<- B
5730    and     r9, r9, #15
5731    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5732    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5733    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5734    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5735    .if 0
5736    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5737    beq     common_errDivideByZero
5738    .endif
5739    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5740
5741    subs    r0, r0, r2                           @ optional op; may set condition codes
5742    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5744    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5745    GOTO_OPCODE(ip)                     @ jump to next instruction
5746    /* 12-15 instructions */
5747
5748
5749/* ------------------------------ */
5750    .balign 64
5751.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5752/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5753    /*
5754     * Signed 64-bit integer multiply, "/2addr" version.
5755     *
5756     * See OP_MUL_LONG for an explanation.
5757     *
5758     * We get a little tight on registers, so to avoid looking up &fp[A]
5759     * again we stuff it into rINST.
5760     */
5761    /* mul-long/2addr vA, vB */
5762    mov     r9, rINST, lsr #8           @ r9<- A+
5763    mov     r1, rINST, lsr #12          @ r1<- B
5764    and     r9, r9, #15
5765    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5766    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5767    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5768    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5769    mul     ip, r2, r1                  @  ip<- ZxW
5770    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5771    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5772    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5773    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5774    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5776    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5777    GOTO_OPCODE(ip)                     @ jump to next instruction
5778
5779/* ------------------------------ */
5780    .balign 64
5781.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5782/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5783/* File: armv5te/binopWide2addr.S */
5784    /*
5785     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5786     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5787     * This could be an ARM instruction or a function call.  (If the result
5788     * comes back in a register other than r0, you can override "result".)
5789     *
5790     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5791     * vCC (r1).  Useful for integer division and modulus.
5792     *
5793     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5794     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5795     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5796     *      rem-double/2addr
5797     */
5798    /* binop/2addr vA, vB */
5799    mov     r9, rINST, lsr #8           @ r9<- A+
5800    mov     r1, rINST, lsr #12          @ r1<- B
5801    and     r9, r9, #15
5802    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5803    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5804    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5805    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5806    .if 1
5807    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5808    beq     common_errDivideByZero
5809    .endif
5810    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5811
5812                               @ optional op; may set condition codes
5813    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5814    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5815    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5816    GOTO_OPCODE(ip)                     @ jump to next instruction
5817    /* 12-15 instructions */
5818
5819
5820/* ------------------------------ */
5821    .balign 64
5822.L_OP_REM_LONG_2ADDR: /* 0xbf */
5823/* File: armv5te/OP_REM_LONG_2ADDR.S */
5824/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5825/* File: armv5te/binopWide2addr.S */
5826    /*
5827     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5828     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5829     * This could be an ARM instruction or a function call.  (If the result
5830     * comes back in a register other than r0, you can override "result".)
5831     *
5832     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5833     * vCC (r1).  Useful for integer division and modulus.
5834     *
5835     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5836     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5837     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5838     *      rem-double/2addr
5839     */
5840    /* binop/2addr vA, vB */
5841    mov     r9, rINST, lsr #8           @ r9<- A+
5842    mov     r1, rINST, lsr #12          @ r1<- B
5843    and     r9, r9, #15
5844    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5845    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5846    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5847    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5848    .if 1
5849    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5850    beq     common_errDivideByZero
5851    .endif
5852    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5853
5854                               @ optional op; may set condition codes
5855    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5857    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5858    GOTO_OPCODE(ip)                     @ jump to next instruction
5859    /* 12-15 instructions */
5860
5861
5862/* ------------------------------ */
5863    .balign 64
5864.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5865/* File: armv5te/OP_AND_LONG_2ADDR.S */
5866/* File: armv5te/binopWide2addr.S */
5867    /*
5868     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5869     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5870     * This could be an ARM instruction or a function call.  (If the result
5871     * comes back in a register other than r0, you can override "result".)
5872     *
5873     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5874     * vCC (r1).  Useful for integer division and modulus.
5875     *
5876     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5877     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5878     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5879     *      rem-double/2addr
5880     */
5881    /* binop/2addr vA, vB */
5882    mov     r9, rINST, lsr #8           @ r9<- A+
5883    mov     r1, rINST, lsr #12          @ r1<- B
5884    and     r9, r9, #15
5885    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5886    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5887    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5888    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5889    .if 0
5890    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5891    beq     common_errDivideByZero
5892    .endif
5893    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5894
5895    and     r0, r0, r2                           @ optional op; may set condition codes
5896    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5898    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5899    GOTO_OPCODE(ip)                     @ jump to next instruction
5900    /* 12-15 instructions */
5901
5902
5903/* ------------------------------ */
5904    .balign 64
5905.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5906/* File: armv5te/OP_OR_LONG_2ADDR.S */
5907/* File: armv5te/binopWide2addr.S */
5908    /*
5909     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5910     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5911     * This could be an ARM instruction or a function call.  (If the result
5912     * comes back in a register other than r0, you can override "result".)
5913     *
5914     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5915     * vCC (r1).  Useful for integer division and modulus.
5916     *
5917     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5918     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5919     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5920     *      rem-double/2addr
5921     */
5922    /* binop/2addr vA, vB */
5923    mov     r9, rINST, lsr #8           @ r9<- A+
5924    mov     r1, rINST, lsr #12          @ r1<- B
5925    and     r9, r9, #15
5926    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5927    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5928    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5929    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5930    .if 0
5931    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5932    beq     common_errDivideByZero
5933    .endif
5934    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5935
5936    orr     r0, r0, r2                           @ optional op; may set condition codes
5937    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5938    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5939    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5940    GOTO_OPCODE(ip)                     @ jump to next instruction
5941    /* 12-15 instructions */
5942
5943
5944/* ------------------------------ */
5945    .balign 64
5946.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5947/* File: armv5te/OP_XOR_LONG_2ADDR.S */
5948/* File: armv5te/binopWide2addr.S */
5949    /*
5950     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5951     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5952     * This could be an ARM instruction or a function call.  (If the result
5953     * comes back in a register other than r0, you can override "result".)
5954     *
5955     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5956     * vCC (r1).  Useful for integer division and modulus.
5957     *
5958     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5959     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5960     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5961     *      rem-double/2addr
5962     */
5963    /* binop/2addr vA, vB */
5964    mov     r9, rINST, lsr #8           @ r9<- A+
5965    mov     r1, rINST, lsr #12          @ r1<- B
5966    and     r9, r9, #15
5967    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5968    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5969    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5970    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5971    .if 0
5972    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5973    beq     common_errDivideByZero
5974    .endif
5975    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5976
5977    eor     r0, r0, r2                           @ optional op; may set condition codes
5978    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5980    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5981    GOTO_OPCODE(ip)                     @ jump to next instruction
5982    /* 12-15 instructions */
5983
5984
5985/* ------------------------------ */
5986    .balign 64
5987.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5988/* File: armv5te/OP_SHL_LONG_2ADDR.S */
5989    /*
5990     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5991     * 32-bit shift distance.
5992     */
5993    /* shl-long/2addr vA, vB */
5994    mov     r9, rINST, lsr #8           @ r9<- A+
5995    mov     r3, rINST, lsr #12          @ r3<- B
5996    and     r9, r9, #15
5997    GET_VREG(r2, r3)                    @ r2<- vB
5998    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5999    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6000    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6001
6002    mov     r1, r1, asl r2              @  r1<- r1 << r2
6003    rsb     r3, r2, #32                 @  r3<- 32 - r2
6004    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6005    subs    ip, r2, #32                 @  ip<- r2 - 32
6006    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6007    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6008    mov     r0, r0, asl r2              @  r0<- r0 << r2
6009    b       .LOP_SHL_LONG_2ADDR_finish
6010
6011/* ------------------------------ */
6012    .balign 64
6013.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6014/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6015    /*
6016     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6017     * 32-bit shift distance.
6018     */
6019    /* shr-long/2addr vA, vB */
6020    mov     r9, rINST, lsr #8           @ r9<- A+
6021    mov     r3, rINST, lsr #12          @ r3<- B
6022    and     r9, r9, #15
6023    GET_VREG(r2, r3)                    @ r2<- vB
6024    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6025    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6026    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6027
6028    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6029    rsb     r3, r2, #32                 @  r3<- 32 - r2
6030    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6031    subs    ip, r2, #32                 @  ip<- r2 - 32
6032    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6033    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6034    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6035    b       .LOP_SHR_LONG_2ADDR_finish
6036
6037/* ------------------------------ */
6038    .balign 64
6039.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6040/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6041    /*
6042     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6043     * 32-bit shift distance.
6044     */
6045    /* ushr-long/2addr vA, vB */
6046    mov     r9, rINST, lsr #8           @ r9<- A+
6047    mov     r3, rINST, lsr #12          @ r3<- B
6048    and     r9, r9, #15
6049    GET_VREG(r2, r3)                    @ r2<- vB
6050    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6051    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6052    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6053
6054    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6055    rsb     r3, r2, #32                 @  r3<- 32 - r2
6056    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6057    subs    ip, r2, #32                 @  ip<- r2 - 32
6058    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6059    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6060    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6061    b       .LOP_USHR_LONG_2ADDR_finish
6062
6063/* ------------------------------ */
6064    .balign 64
6065.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6066/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6067/* File: arm-vfp/fbinop2addr.S */
6068    /*
6069     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6070     * an "instr" line that specifies an instruction that performs
6071     * "s2 = s0 op s1".
6072     *
6073     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6074     */
6075    /* binop/2addr vA, vB */
6076    mov     r3, rINST, lsr #12          @ r3<- B
6077    mov     r9, rINST, lsr #8           @ r9<- A+
6078    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6079    and     r9, r9, #15                 @ r9<- A
6080    flds    s1, [r3]                    @ s1<- vB
6081    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6082    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6083    flds    s0, [r9]                    @ s0<- vA
6084
6085    fadds   s2, s0, s1                              @ s2<- op
6086    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6087    fsts    s2, [r9]                    @ vAA<- s2
6088    GOTO_OPCODE(ip)                     @ jump to next instruction
6089
6090
6091/* ------------------------------ */
6092    .balign 64
6093.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6094/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6095/* File: arm-vfp/fbinop2addr.S */
6096    /*
6097     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6098     * an "instr" line that specifies an instruction that performs
6099     * "s2 = s0 op s1".
6100     *
6101     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6102     */
6103    /* binop/2addr vA, vB */
6104    mov     r3, rINST, lsr #12          @ r3<- B
6105    mov     r9, rINST, lsr #8           @ r9<- A+
6106    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6107    and     r9, r9, #15                 @ r9<- A
6108    flds    s1, [r3]                    @ s1<- vB
6109    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6110    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6111    flds    s0, [r9]                    @ s0<- vA
6112
6113    fsubs   s2, s0, s1                              @ s2<- op
6114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6115    fsts    s2, [r9]                    @ vAA<- s2
6116    GOTO_OPCODE(ip)                     @ jump to next instruction
6117
6118
6119/* ------------------------------ */
6120    .balign 64
6121.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6122/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6123/* File: arm-vfp/fbinop2addr.S */
6124    /*
6125     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6126     * an "instr" line that specifies an instruction that performs
6127     * "s2 = s0 op s1".
6128     *
6129     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6130     */
6131    /* binop/2addr vA, vB */
6132    mov     r3, rINST, lsr #12          @ r3<- B
6133    mov     r9, rINST, lsr #8           @ r9<- A+
6134    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6135    and     r9, r9, #15                 @ r9<- A
6136    flds    s1, [r3]                    @ s1<- vB
6137    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6138    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6139    flds    s0, [r9]                    @ s0<- vA
6140
6141    fmuls   s2, s0, s1                              @ s2<- op
6142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6143    fsts    s2, [r9]                    @ vAA<- s2
6144    GOTO_OPCODE(ip)                     @ jump to next instruction
6145
6146
6147/* ------------------------------ */
6148    .balign 64
6149.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6150/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6151/* File: arm-vfp/fbinop2addr.S */
6152    /*
6153     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6154     * an "instr" line that specifies an instruction that performs
6155     * "s2 = s0 op s1".
6156     *
6157     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6158     */
6159    /* binop/2addr vA, vB */
6160    mov     r3, rINST, lsr #12          @ r3<- B
6161    mov     r9, rINST, lsr #8           @ r9<- A+
6162    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6163    and     r9, r9, #15                 @ r9<- A
6164    flds    s1, [r3]                    @ s1<- vB
6165    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6166    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6167    flds    s0, [r9]                    @ s0<- vA
6168
6169    fdivs   s2, s0, s1                              @ s2<- op
6170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6171    fsts    s2, [r9]                    @ vAA<- s2
6172    GOTO_OPCODE(ip)                     @ jump to next instruction
6173
6174
6175/* ------------------------------ */
6176    .balign 64
6177.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6178/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6179/* EABI doesn't define a float remainder function, but libm does */
6180/* File: armv5te/binop2addr.S */
6181    /*
6182     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6183     * that specifies an instruction that performs "result = r0 op r1".
6184     * This could be an ARM instruction or a function call.  (If the result
6185     * comes back in a register other than r0, you can override "result".)
6186     *
6187     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6188     * vCC (r1).  Useful for integer division and modulus.
6189     *
6190     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6191     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6192     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6193     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6194     */
6195    /* binop/2addr vA, vB */
6196    mov     r9, rINST, lsr #8           @ r9<- A+
6197    mov     r3, rINST, lsr #12          @ r3<- B
6198    and     r9, r9, #15
6199    GET_VREG(r1, r3)                    @ r1<- vB
6200    GET_VREG(r0, r9)                    @ r0<- vA
6201    .if 0
6202    cmp     r1, #0                      @ is second operand zero?
6203    beq     common_errDivideByZero
6204    .endif
6205    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6206
6207                               @ optional op; may set condition codes
6208    bl      fmodf                              @ r0<- op, r0-r3 changed
6209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6210    SET_VREG(r0, r9)               @ vAA<- r0
6211    GOTO_OPCODE(ip)                     @ jump to next instruction
6212    /* 10-13 instructions */
6213
6214
6215/* ------------------------------ */
6216    .balign 64
6217.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6218/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6219/* File: arm-vfp/fbinopWide2addr.S */
6220    /*
6221     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6222     * an "instr" line that specifies an instruction that performs
6223     * "d2 = d0 op d1".
6224     *
6225     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6226     *      div-double/2addr
6227     */
6228    /* binop/2addr vA, vB */
6229    mov     r3, rINST, lsr #12          @ r3<- B
6230    mov     r9, rINST, lsr #8           @ r9<- A+
6231    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6232    and     r9, r9, #15                 @ r9<- A
6233    fldd    d1, [r3]                    @ d1<- vB
6234    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6235    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6236    fldd    d0, [r9]                    @ d0<- vA
6237
6238    faddd   d2, d0, d1                              @ d2<- op
6239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6240    fstd    d2, [r9]                    @ vAA<- d2
6241    GOTO_OPCODE(ip)                     @ jump to next instruction
6242
6243
6244/* ------------------------------ */
6245    .balign 64
6246.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6247/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6248/* File: arm-vfp/fbinopWide2addr.S */
6249    /*
6250     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6251     * an "instr" line that specifies an instruction that performs
6252     * "d2 = d0 op d1".
6253     *
6254     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6255     *      div-double/2addr
6256     */
6257    /* binop/2addr vA, vB */
6258    mov     r3, rINST, lsr #12          @ r3<- B
6259    mov     r9, rINST, lsr #8           @ r9<- A+
6260    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6261    and     r9, r9, #15                 @ r9<- A
6262    fldd    d1, [r3]                    @ d1<- vB
6263    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6264    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265    fldd    d0, [r9]                    @ d0<- vA
6266
6267    fsubd   d2, d0, d1                              @ d2<- op
6268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269    fstd    d2, [r9]                    @ vAA<- d2
6270    GOTO_OPCODE(ip)                     @ jump to next instruction
6271
6272
6273/* ------------------------------ */
6274    .balign 64
6275.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6276/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6277/* File: arm-vfp/fbinopWide2addr.S */
6278    /*
6279     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6280     * an "instr" line that specifies an instruction that performs
6281     * "d2 = d0 op d1".
6282     *
6283     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6284     *      div-double/2addr
6285     */
6286    /* binop/2addr vA, vB */
6287    mov     r3, rINST, lsr #12          @ r3<- B
6288    mov     r9, rINST, lsr #8           @ r9<- A+
6289    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6290    and     r9, r9, #15                 @ r9<- A
6291    fldd    d1, [r3]                    @ d1<- vB
6292    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6293    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6294    fldd    d0, [r9]                    @ d0<- vA
6295
6296    fmuld   d2, d0, d1                              @ d2<- op
6297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6298    fstd    d2, [r9]                    @ vAA<- d2
6299    GOTO_OPCODE(ip)                     @ jump to next instruction
6300
6301
6302/* ------------------------------ */
6303    .balign 64
6304.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6305/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6306/* File: arm-vfp/fbinopWide2addr.S */
6307    /*
6308     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6309     * an "instr" line that specifies an instruction that performs
6310     * "d2 = d0 op d1".
6311     *
6312     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6313     *      div-double/2addr
6314     */
6315    /* binop/2addr vA, vB */
6316    mov     r3, rINST, lsr #12          @ r3<- B
6317    mov     r9, rINST, lsr #8           @ r9<- A+
6318    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6319    and     r9, r9, #15                 @ r9<- A
6320    fldd    d1, [r3]                    @ d1<- vB
6321    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6322    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6323    fldd    d0, [r9]                    @ d0<- vA
6324
6325    fdivd   d2, d0, d1                              @ d2<- op
6326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6327    fstd    d2, [r9]                    @ vAA<- d2
6328    GOTO_OPCODE(ip)                     @ jump to next instruction
6329
6330
6331/* ------------------------------ */
6332    .balign 64
6333.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6334/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6335/* EABI doesn't define a double remainder function, but libm does */
6336/* File: armv5te/binopWide2addr.S */
6337    /*
6338     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6339     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6340     * This could be an ARM instruction or a function call.  (If the result
6341     * comes back in a register other than r0, you can override "result".)
6342     *
6343     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6344     * vCC (r1).  Useful for integer division and modulus.
6345     *
6346     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6347     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6348     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6349     *      rem-double/2addr
6350     */
6351    /* binop/2addr vA, vB */
6352    mov     r9, rINST, lsr #8           @ r9<- A+
6353    mov     r1, rINST, lsr #12          @ r1<- B
6354    and     r9, r9, #15
6355    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6356    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6357    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6358    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6359    .if 0
6360    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6361    beq     common_errDivideByZero
6362    .endif
6363    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6364
6365                               @ optional op; may set condition codes
6366    bl      fmod                              @ result<- op, r0-r3 changed
6367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6368    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6369    GOTO_OPCODE(ip)                     @ jump to next instruction
6370    /* 12-15 instructions */
6371
6372
6373/* ------------------------------ */
6374    .balign 64
6375.L_OP_ADD_INT_LIT16: /* 0xd0 */
6376/* File: armv5te/OP_ADD_INT_LIT16.S */
6377/* File: armv5te/binopLit16.S */
6378    /*
6379     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6380     * that specifies an instruction that performs "result = r0 op r1".
6381     * This could be an ARM instruction or a function call.  (If the result
6382     * comes back in a register other than r0, you can override "result".)
6383     *
6384     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6385     * vCC (r1).  Useful for integer division and modulus.
6386     *
6387     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6388     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6389     */
6390    /* binop/lit16 vA, vB, #+CCCC */
6391    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6392    mov     r2, rINST, lsr #12          @ r2<- B
6393    mov     r9, rINST, lsr #8           @ r9<- A+
6394    GET_VREG(r0, r2)                    @ r0<- vB
6395    and     r9, r9, #15
6396    .if 0
6397    cmp     r1, #0                      @ is second operand zero?
6398    beq     common_errDivideByZero
6399    .endif
6400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6401
6402    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6403    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6404    SET_VREG(r0, r9)               @ vAA<- r0
6405    GOTO_OPCODE(ip)                     @ jump to next instruction
6406    /* 10-13 instructions */
6407
6408
6409/* ------------------------------ */
6410    .balign 64
6411.L_OP_RSUB_INT: /* 0xd1 */
6412/* File: armv5te/OP_RSUB_INT.S */
6413/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6414/* File: armv5te/binopLit16.S */
6415    /*
6416     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6417     * that specifies an instruction that performs "result = r0 op r1".
6418     * This could be an ARM instruction or a function call.  (If the result
6419     * comes back in a register other than r0, you can override "result".)
6420     *
6421     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6422     * vCC (r1).  Useful for integer division and modulus.
6423     *
6424     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6425     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6426     */
6427    /* binop/lit16 vA, vB, #+CCCC */
6428    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6429    mov     r2, rINST, lsr #12          @ r2<- B
6430    mov     r9, rINST, lsr #8           @ r9<- A+
6431    GET_VREG(r0, r2)                    @ r0<- vB
6432    and     r9, r9, #15
6433    .if 0
6434    cmp     r1, #0                      @ is second operand zero?
6435    beq     common_errDivideByZero
6436    .endif
6437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6438
6439    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6441    SET_VREG(r0, r9)               @ vAA<- r0
6442    GOTO_OPCODE(ip)                     @ jump to next instruction
6443    /* 10-13 instructions */
6444
6445
6446/* ------------------------------ */
6447    .balign 64
6448.L_OP_MUL_INT_LIT16: /* 0xd2 */
6449/* File: armv5te/OP_MUL_INT_LIT16.S */
6450/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6451/* File: armv5te/binopLit16.S */
6452    /*
6453     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6454     * that specifies an instruction that performs "result = r0 op r1".
6455     * This could be an ARM instruction or a function call.  (If the result
6456     * comes back in a register other than r0, you can override "result".)
6457     *
6458     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6459     * vCC (r1).  Useful for integer division and modulus.
6460     *
6461     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6462     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6463     */
6464    /* binop/lit16 vA, vB, #+CCCC */
6465    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6466    mov     r2, rINST, lsr #12          @ r2<- B
6467    mov     r9, rINST, lsr #8           @ r9<- A+
6468    GET_VREG(r0, r2)                    @ r0<- vB
6469    and     r9, r9, #15
6470    .if 0
6471    cmp     r1, #0                      @ is second operand zero?
6472    beq     common_errDivideByZero
6473    .endif
6474    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6475
6476    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6477    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6478    SET_VREG(r0, r9)               @ vAA<- r0
6479    GOTO_OPCODE(ip)                     @ jump to next instruction
6480    /* 10-13 instructions */
6481
6482
6483/* ------------------------------ */
6484    .balign 64
6485.L_OP_DIV_INT_LIT16: /* 0xd3 */
6486/* File: armv5te/OP_DIV_INT_LIT16.S */
6487/* File: armv5te/binopLit16.S */
6488    /*
6489     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6490     * that specifies an instruction that performs "result = r0 op r1".
6491     * This could be an ARM instruction or a function call.  (If the result
6492     * comes back in a register other than r0, you can override "result".)
6493     *
6494     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6495     * vCC (r1).  Useful for integer division and modulus.
6496     *
6497     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6498     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6499     */
6500    /* binop/lit16 vA, vB, #+CCCC */
6501    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6502    mov     r2, rINST, lsr #12          @ r2<- B
6503    mov     r9, rINST, lsr #8           @ r9<- A+
6504    GET_VREG(r0, r2)                    @ r0<- vB
6505    and     r9, r9, #15
6506    .if 1
6507    cmp     r1, #0                      @ is second operand zero?
6508    beq     common_errDivideByZero
6509    .endif
6510    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6511
6512    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6514    SET_VREG(r0, r9)               @ vAA<- r0
6515    GOTO_OPCODE(ip)                     @ jump to next instruction
6516    /* 10-13 instructions */
6517
6518
6519/* ------------------------------ */
6520    .balign 64
6521.L_OP_REM_INT_LIT16: /* 0xd4 */
6522/* File: armv5te/OP_REM_INT_LIT16.S */
6523/* idivmod returns quotient in r0 and remainder in r1 */
6524/* File: armv5te/binopLit16.S */
6525    /*
6526     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6527     * that specifies an instruction that performs "result = r0 op r1".
6528     * This could be an ARM instruction or a function call.  (If the result
6529     * comes back in a register other than r0, you can override "result".)
6530     *
6531     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6532     * vCC (r1).  Useful for integer division and modulus.
6533     *
6534     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6535     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6536     */
6537    /* binop/lit16 vA, vB, #+CCCC */
6538    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6539    mov     r2, rINST, lsr #12          @ r2<- B
6540    mov     r9, rINST, lsr #8           @ r9<- A+
6541    GET_VREG(r0, r2)                    @ r0<- vB
6542    and     r9, r9, #15
6543    .if 1
6544    cmp     r1, #0                      @ is second operand zero?
6545    beq     common_errDivideByZero
6546    .endif
6547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6548
6549    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6550    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6551    SET_VREG(r1, r9)               @ vAA<- r1
6552    GOTO_OPCODE(ip)                     @ jump to next instruction
6553    /* 10-13 instructions */
6554
6555
6556/* ------------------------------ */
6557    .balign 64
6558.L_OP_AND_INT_LIT16: /* 0xd5 */
6559/* File: armv5te/OP_AND_INT_LIT16.S */
6560/* File: armv5te/binopLit16.S */
6561    /*
6562     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6563     * that specifies an instruction that performs "result = r0 op r1".
6564     * This could be an ARM instruction or a function call.  (If the result
6565     * comes back in a register other than r0, you can override "result".)
6566     *
6567     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6568     * vCC (r1).  Useful for integer division and modulus.
6569     *
6570     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6571     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6572     */
6573    /* binop/lit16 vA, vB, #+CCCC */
6574    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6575    mov     r2, rINST, lsr #12          @ r2<- B
6576    mov     r9, rINST, lsr #8           @ r9<- A+
6577    GET_VREG(r0, r2)                    @ r0<- vB
6578    and     r9, r9, #15
6579    .if 0
6580    cmp     r1, #0                      @ is second operand zero?
6581    beq     common_errDivideByZero
6582    .endif
6583    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6584
6585    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6587    SET_VREG(r0, r9)               @ vAA<- r0
6588    GOTO_OPCODE(ip)                     @ jump to next instruction
6589    /* 10-13 instructions */
6590
6591
6592/* ------------------------------ */
6593    .balign 64
6594.L_OP_OR_INT_LIT16: /* 0xd6 */
6595/* File: armv5te/OP_OR_INT_LIT16.S */
6596/* File: armv5te/binopLit16.S */
6597    /*
6598     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6599     * that specifies an instruction that performs "result = r0 op r1".
6600     * This could be an ARM instruction or a function call.  (If the result
6601     * comes back in a register other than r0, you can override "result".)
6602     *
6603     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6604     * vCC (r1).  Useful for integer division and modulus.
6605     *
6606     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6607     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6608     */
6609    /* binop/lit16 vA, vB, #+CCCC */
6610    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6611    mov     r2, rINST, lsr #12          @ r2<- B
6612    mov     r9, rINST, lsr #8           @ r9<- A+
6613    GET_VREG(r0, r2)                    @ r0<- vB
6614    and     r9, r9, #15
6615    .if 0
6616    cmp     r1, #0                      @ is second operand zero?
6617    beq     common_errDivideByZero
6618    .endif
6619    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6620
6621    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6623    SET_VREG(r0, r9)               @ vAA<- r0
6624    GOTO_OPCODE(ip)                     @ jump to next instruction
6625    /* 10-13 instructions */
6626
6627
6628/* ------------------------------ */
6629    .balign 64
6630.L_OP_XOR_INT_LIT16: /* 0xd7 */
6631/* File: armv5te/OP_XOR_INT_LIT16.S */
6632/* File: armv5te/binopLit16.S */
6633    /*
6634     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6635     * that specifies an instruction that performs "result = r0 op r1".
6636     * This could be an ARM instruction or a function call.  (If the result
6637     * comes back in a register other than r0, you can override "result".)
6638     *
6639     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6640     * vCC (r1).  Useful for integer division and modulus.
6641     *
6642     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6643     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6644     */
6645    /* binop/lit16 vA, vB, #+CCCC */
6646    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6647    mov     r2, rINST, lsr #12          @ r2<- B
6648    mov     r9, rINST, lsr #8           @ r9<- A+
6649    GET_VREG(r0, r2)                    @ r0<- vB
6650    and     r9, r9, #15
6651    .if 0
6652    cmp     r1, #0                      @ is second operand zero?
6653    beq     common_errDivideByZero
6654    .endif
6655    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6656
6657    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6658    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6659    SET_VREG(r0, r9)               @ vAA<- r0
6660    GOTO_OPCODE(ip)                     @ jump to next instruction
6661    /* 10-13 instructions */
6662
6663
6664/* ------------------------------ */
6665    .balign 64
6666.L_OP_ADD_INT_LIT8: /* 0xd8 */
6667/* File: armv5te/OP_ADD_INT_LIT8.S */
6668/* File: armv5te/binopLit8.S */
6669    /*
6670     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6671     * that specifies an instruction that performs "result = r0 op r1".
6672     * This could be an ARM instruction or a function call.  (If the result
6673     * comes back in a register other than r0, you can override "result".)
6674     *
6675     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6676     * vCC (r1).  Useful for integer division and modulus.
6677     *
6678     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6679     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6680     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6681     */
6682    /* binop/lit8 vAA, vBB, #+CC */
6683    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6684    mov     r9, rINST, lsr #8           @ r9<- AA
6685    and     r2, r3, #255                @ r2<- BB
6686    GET_VREG(r0, r2)                    @ r0<- vBB
6687    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6688    .if 0
6689    @cmp     r1, #0                      @ is second operand zero?
6690    beq     common_errDivideByZero
6691    .endif
6692    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6693
6694                               @ optional op; may set condition codes
6695    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6697    SET_VREG(r0, r9)               @ vAA<- r0
6698    GOTO_OPCODE(ip)                     @ jump to next instruction
6699    /* 10-12 instructions */
6700
6701
6702/* ------------------------------ */
6703    .balign 64
6704.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6705/* File: armv5te/OP_RSUB_INT_LIT8.S */
6706/* File: armv5te/binopLit8.S */
6707    /*
6708     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6709     * that specifies an instruction that performs "result = r0 op r1".
6710     * This could be an ARM instruction or a function call.  (If the result
6711     * comes back in a register other than r0, you can override "result".)
6712     *
6713     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6714     * vCC (r1).  Useful for integer division and modulus.
6715     *
6716     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6717     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6718     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6719     */
6720    /* binop/lit8 vAA, vBB, #+CC */
6721    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6722    mov     r9, rINST, lsr #8           @ r9<- AA
6723    and     r2, r3, #255                @ r2<- BB
6724    GET_VREG(r0, r2)                    @ r0<- vBB
6725    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6726    .if 0
6727    @cmp     r1, #0                      @ is second operand zero?
6728    beq     common_errDivideByZero
6729    .endif
6730    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6731
6732                               @ optional op; may set condition codes
6733    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6734    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6735    SET_VREG(r0, r9)               @ vAA<- r0
6736    GOTO_OPCODE(ip)                     @ jump to next instruction
6737    /* 10-12 instructions */
6738
6739
6740/* ------------------------------ */
6741    .balign 64
6742.L_OP_MUL_INT_LIT8: /* 0xda */
6743/* File: armv5te/OP_MUL_INT_LIT8.S */
6744/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6745/* File: armv5te/binopLit8.S */
6746    /*
6747     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6748     * that specifies an instruction that performs "result = r0 op r1".
6749     * This could be an ARM instruction or a function call.  (If the result
6750     * comes back in a register other than r0, you can override "result".)
6751     *
6752     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6753     * vCC (r1).  Useful for integer division and modulus.
6754     *
6755     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6756     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6757     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6758     */
6759    /* binop/lit8 vAA, vBB, #+CC */
6760    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6761    mov     r9, rINST, lsr #8           @ r9<- AA
6762    and     r2, r3, #255                @ r2<- BB
6763    GET_VREG(r0, r2)                    @ r0<- vBB
6764    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6765    .if 0
6766    @cmp     r1, #0                      @ is second operand zero?
6767    beq     common_errDivideByZero
6768    .endif
6769    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6770
6771                               @ optional op; may set condition codes
6772    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6773    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6774    SET_VREG(r0, r9)               @ vAA<- r0
6775    GOTO_OPCODE(ip)                     @ jump to next instruction
6776    /* 10-12 instructions */
6777
6778
6779/* ------------------------------ */
6780    .balign 64
6781.L_OP_DIV_INT_LIT8: /* 0xdb */
6782/* File: armv5te/OP_DIV_INT_LIT8.S */
6783/* File: armv5te/binopLit8.S */
6784    /*
6785     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6786     * that specifies an instruction that performs "result = r0 op r1".
6787     * This could be an ARM instruction or a function call.  (If the result
6788     * comes back in a register other than r0, you can override "result".)
6789     *
6790     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6791     * vCC (r1).  Useful for integer division and modulus.
6792     *
6793     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6794     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6795     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6796     */
6797    /* binop/lit8 vAA, vBB, #+CC */
6798    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6799    mov     r9, rINST, lsr #8           @ r9<- AA
6800    and     r2, r3, #255                @ r2<- BB
6801    GET_VREG(r0, r2)                    @ r0<- vBB
6802    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6803    .if 1
6804    @cmp     r1, #0                      @ is second operand zero?
6805    beq     common_errDivideByZero
6806    .endif
6807    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6808
6809                               @ optional op; may set condition codes
6810    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6812    SET_VREG(r0, r9)               @ vAA<- r0
6813    GOTO_OPCODE(ip)                     @ jump to next instruction
6814    /* 10-12 instructions */
6815
6816
6817/* ------------------------------ */
6818    .balign 64
6819.L_OP_REM_INT_LIT8: /* 0xdc */
6820/* File: armv5te/OP_REM_INT_LIT8.S */
6821/* idivmod returns quotient in r0 and remainder in r1 */
6822/* File: armv5te/binopLit8.S */
6823    /*
6824     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6825     * that specifies an instruction that performs "result = r0 op r1".
6826     * This could be an ARM instruction or a function call.  (If the result
6827     * comes back in a register other than r0, you can override "result".)
6828     *
6829     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6830     * vCC (r1).  Useful for integer division and modulus.
6831     *
6832     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6833     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6834     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6835     */
6836    /* binop/lit8 vAA, vBB, #+CC */
6837    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6838    mov     r9, rINST, lsr #8           @ r9<- AA
6839    and     r2, r3, #255                @ r2<- BB
6840    GET_VREG(r0, r2)                    @ r0<- vBB
6841    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6842    .if 1
6843    @cmp     r1, #0                      @ is second operand zero?
6844    beq     common_errDivideByZero
6845    .endif
6846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6847
6848                               @ optional op; may set condition codes
6849    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6851    SET_VREG(r1, r9)               @ vAA<- r1
6852    GOTO_OPCODE(ip)                     @ jump to next instruction
6853    /* 10-12 instructions */
6854
6855
6856/* ------------------------------ */
6857    .balign 64
6858.L_OP_AND_INT_LIT8: /* 0xdd */
6859/* File: armv5te/OP_AND_INT_LIT8.S */
6860/* File: armv5te/binopLit8.S */
6861    /*
6862     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6863     * that specifies an instruction that performs "result = r0 op r1".
6864     * This could be an ARM instruction or a function call.  (If the result
6865     * comes back in a register other than r0, you can override "result".)
6866     *
6867     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6868     * vCC (r1).  Useful for integer division and modulus.
6869     *
6870     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6871     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6872     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6873     */
6874    /* binop/lit8 vAA, vBB, #+CC */
6875    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6876    mov     r9, rINST, lsr #8           @ r9<- AA
6877    and     r2, r3, #255                @ r2<- BB
6878    GET_VREG(r0, r2)                    @ r0<- vBB
6879    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6880    .if 0
6881    @cmp     r1, #0                      @ is second operand zero?
6882    beq     common_errDivideByZero
6883    .endif
6884    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6885
6886                               @ optional op; may set condition codes
6887    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6889    SET_VREG(r0, r9)               @ vAA<- r0
6890    GOTO_OPCODE(ip)                     @ jump to next instruction
6891    /* 10-12 instructions */
6892
6893
6894/* ------------------------------ */
6895    .balign 64
6896.L_OP_OR_INT_LIT8: /* 0xde */
6897/* File: armv5te/OP_OR_INT_LIT8.S */
6898/* File: armv5te/binopLit8.S */
6899    /*
6900     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6901     * that specifies an instruction that performs "result = r0 op r1".
6902     * This could be an ARM instruction or a function call.  (If the result
6903     * comes back in a register other than r0, you can override "result".)
6904     *
6905     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6906     * vCC (r1).  Useful for integer division and modulus.
6907     *
6908     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6909     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6910     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6911     */
6912    /* binop/lit8 vAA, vBB, #+CC */
6913    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6914    mov     r9, rINST, lsr #8           @ r9<- AA
6915    and     r2, r3, #255                @ r2<- BB
6916    GET_VREG(r0, r2)                    @ r0<- vBB
6917    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6918    .if 0
6919    @cmp     r1, #0                      @ is second operand zero?
6920    beq     common_errDivideByZero
6921    .endif
6922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6923
6924                               @ optional op; may set condition codes
6925    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6926    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6927    SET_VREG(r0, r9)               @ vAA<- r0
6928    GOTO_OPCODE(ip)                     @ jump to next instruction
6929    /* 10-12 instructions */
6930
6931
6932/* ------------------------------ */
6933    .balign 64
6934.L_OP_XOR_INT_LIT8: /* 0xdf */
6935/* File: armv5te/OP_XOR_INT_LIT8.S */
6936/* File: armv5te/binopLit8.S */
6937    /*
6938     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6939     * that specifies an instruction that performs "result = r0 op r1".
6940     * This could be an ARM instruction or a function call.  (If the result
6941     * comes back in a register other than r0, you can override "result".)
6942     *
6943     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6944     * vCC (r1).  Useful for integer division and modulus.
6945     *
6946     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6947     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6948     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6949     */
6950    /* binop/lit8 vAA, vBB, #+CC */
6951    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6952    mov     r9, rINST, lsr #8           @ r9<- AA
6953    and     r2, r3, #255                @ r2<- BB
6954    GET_VREG(r0, r2)                    @ r0<- vBB
6955    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6956    .if 0
6957    @cmp     r1, #0                      @ is second operand zero?
6958    beq     common_errDivideByZero
6959    .endif
6960    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6961
6962                               @ optional op; may set condition codes
6963    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6964    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6965    SET_VREG(r0, r9)               @ vAA<- r0
6966    GOTO_OPCODE(ip)                     @ jump to next instruction
6967    /* 10-12 instructions */
6968
6969
6970/* ------------------------------ */
6971    .balign 64
6972.L_OP_SHL_INT_LIT8: /* 0xe0 */
6973/* File: armv5te/OP_SHL_INT_LIT8.S */
6974/* File: armv5te/binopLit8.S */
6975    /*
6976     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6977     * that specifies an instruction that performs "result = r0 op r1".
6978     * This could be an ARM instruction or a function call.  (If the result
6979     * comes back in a register other than r0, you can override "result".)
6980     *
6981     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6982     * vCC (r1).  Useful for integer division and modulus.
6983     *
6984     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6985     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6986     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6987     */
6988    /* binop/lit8 vAA, vBB, #+CC */
6989    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6990    mov     r9, rINST, lsr #8           @ r9<- AA
6991    and     r2, r3, #255                @ r2<- BB
6992    GET_VREG(r0, r2)                    @ r0<- vBB
6993    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6994    .if 0
6995    @cmp     r1, #0                      @ is second operand zero?
6996    beq     common_errDivideByZero
6997    .endif
6998    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6999
7000    and     r1, r1, #31                           @ optional op; may set condition codes
7001    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7003    SET_VREG(r0, r9)               @ vAA<- r0
7004    GOTO_OPCODE(ip)                     @ jump to next instruction
7005    /* 10-12 instructions */
7006
7007
7008/* ------------------------------ */
7009    .balign 64
7010.L_OP_SHR_INT_LIT8: /* 0xe1 */
7011/* File: armv5te/OP_SHR_INT_LIT8.S */
7012/* File: armv5te/binopLit8.S */
7013    /*
7014     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7015     * that specifies an instruction that performs "result = r0 op r1".
7016     * This could be an ARM instruction or a function call.  (If the result
7017     * comes back in a register other than r0, you can override "result".)
7018     *
7019     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7020     * vCC (r1).  Useful for integer division and modulus.
7021     *
7022     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7023     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7024     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7025     */
7026    /* binop/lit8 vAA, vBB, #+CC */
7027    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7028    mov     r9, rINST, lsr #8           @ r9<- AA
7029    and     r2, r3, #255                @ r2<- BB
7030    GET_VREG(r0, r2)                    @ r0<- vBB
7031    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7032    .if 0
7033    @cmp     r1, #0                      @ is second operand zero?
7034    beq     common_errDivideByZero
7035    .endif
7036    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7037
7038    and     r1, r1, #31                           @ optional op; may set condition codes
7039    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7041    SET_VREG(r0, r9)               @ vAA<- r0
7042    GOTO_OPCODE(ip)                     @ jump to next instruction
7043    /* 10-12 instructions */
7044
7045
7046/* ------------------------------ */
7047    .balign 64
7048.L_OP_USHR_INT_LIT8: /* 0xe2 */
7049/* File: armv5te/OP_USHR_INT_LIT8.S */
7050/* File: armv5te/binopLit8.S */
7051    /*
7052     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7053     * that specifies an instruction that performs "result = r0 op r1".
7054     * This could be an ARM instruction or a function call.  (If the result
7055     * comes back in a register other than r0, you can override "result".)
7056     *
7057     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7058     * vCC (r1).  Useful for integer division and modulus.
7059     *
7060     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7061     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7062     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7063     */
7064    /* binop/lit8 vAA, vBB, #+CC */
7065    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7066    mov     r9, rINST, lsr #8           @ r9<- AA
7067    and     r2, r3, #255                @ r2<- BB
7068    GET_VREG(r0, r2)                    @ r0<- vBB
7069    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7070    .if 0
7071    @cmp     r1, #0                      @ is second operand zero?
7072    beq     common_errDivideByZero
7073    .endif
7074    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7075
7076    and     r1, r1, #31                           @ optional op; may set condition codes
7077    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7079    SET_VREG(r0, r9)               @ vAA<- r0
7080    GOTO_OPCODE(ip)                     @ jump to next instruction
7081    /* 10-12 instructions */
7082
7083
7084/* ------------------------------ */
7085    .balign 64
7086.L_OP_IGET_VOLATILE: /* 0xe3 */
7087/* File: armv5te/OP_IGET_VOLATILE.S */
7088/* File: armv5te/OP_IGET.S */
7089    /*
7090     * General 32-bit instance field get.
7091     *
7092     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7093     */
7094    /* op vA, vB, field@CCCC */
7095    mov     r0, rINST, lsr #12          @ r0<- B
7096    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7097    FETCH(r1, 1)                        @ r1<- field ref CCCC
7098    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7099    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7100    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7101    cmp     r0, #0                      @ is resolved entry null?
7102    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
71038:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7104    EXPORT_PC()                         @ resolve() could throw
7105    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7106    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7107    cmp     r0, #0
7108    bne     .LOP_IGET_VOLATILE_finish
7109    b       common_exceptionThrown
7110
7111
7112/* ------------------------------ */
7113    .balign 64
7114.L_OP_IPUT_VOLATILE: /* 0xe4 */
7115/* File: armv5te/OP_IPUT_VOLATILE.S */
7116/* File: armv5te/OP_IPUT.S */
7117    /*
7118     * General 32-bit instance field put.
7119     *
7120     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7121     */
7122    /* op vA, vB, field@CCCC */
7123    mov     r0, rINST, lsr #12          @ r0<- B
7124    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7125    FETCH(r1, 1)                        @ r1<- field ref CCCC
7126    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7127    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7128    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7129    cmp     r0, #0                      @ is resolved entry null?
7130    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71318:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7132    EXPORT_PC()                         @ resolve() could throw
7133    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7134    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7135    cmp     r0, #0                      @ success?
7136    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7137    b       common_exceptionThrown
7138
7139
7140/* ------------------------------ */
7141    .balign 64
7142.L_OP_SGET_VOLATILE: /* 0xe5 */
7143/* File: armv5te/OP_SGET_VOLATILE.S */
7144/* File: armv5te/OP_SGET.S */
7145    /*
7146     * General 32-bit SGET handler.
7147     *
7148     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7149     */
7150    /* op vAA, field@BBBB */
7151    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7152    FETCH(r1, 1)                        @ r1<- field ref BBBB
7153    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7154    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7155    cmp     r0, #0                      @ is resolved entry null?
7156    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7157.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7158    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7159    SMP_DMB                            @ acquiring load
7160    mov     r2, rINST, lsr #8           @ r2<- AA
7161    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7162    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7163    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7164    GOTO_OPCODE(ip)                     @ jump to next instruction
7165
7166
7167/* ------------------------------ */
7168    .balign 64
7169.L_OP_SPUT_VOLATILE: /* 0xe6 */
7170/* File: armv5te/OP_SPUT_VOLATILE.S */
7171/* File: armv5te/OP_SPUT.S */
7172    /*
7173     * General 32-bit SPUT handler.
7174     *
7175     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7176     */
7177    /* op vAA, field@BBBB */
7178    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7179    FETCH(r1, 1)                        @ r1<- field ref BBBB
7180    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7181    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7182    cmp     r0, #0                      @ is resolved entry null?
7183    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7184.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7185    mov     r2, rINST, lsr #8           @ r2<- AA
7186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7187    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7189    SMP_DMB                            @ releasing store
7190    str     r1, [r0, #offStaticField_value] @ field<- vAA
7191    GOTO_OPCODE(ip)                     @ jump to next instruction
7192
7193
7194/* ------------------------------ */
7195    .balign 64
7196.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7197/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7198/* File: armv5te/OP_IGET.S */
7199    /*
7200     * General 32-bit instance field get.
7201     *
7202     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7203     */
7204    /* op vA, vB, field@CCCC */
7205    mov     r0, rINST, lsr #12          @ r0<- B
7206    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7207    FETCH(r1, 1)                        @ r1<- field ref CCCC
7208    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7209    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7210    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7211    cmp     r0, #0                      @ is resolved entry null?
7212    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
72138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7214    EXPORT_PC()                         @ resolve() could throw
7215    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7216    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7217    cmp     r0, #0
7218    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7219    b       common_exceptionThrown
7220
7221
7222/* ------------------------------ */
7223    .balign 64
7224.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7225/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7226/* File: armv5te/OP_IGET_WIDE.S */
7227    /*
7228     * Wide 32-bit instance field get.
7229     */
7230    /* iget-wide vA, vB, field@CCCC */
7231    mov     r0, rINST, lsr #12          @ r0<- B
7232    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7233    FETCH(r1, 1)                        @ r1<- field ref CCCC
7234    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7235    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7236    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7237    cmp     r0, #0                      @ is resolved entry null?
7238    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72398:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7240    EXPORT_PC()                         @ resolve() could throw
7241    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7242    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7243    cmp     r0, #0
7244    bne     .LOP_IGET_WIDE_VOLATILE_finish
7245    b       common_exceptionThrown
7246
7247
7248/* ------------------------------ */
7249    .balign 64
7250.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7251/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7252/* File: armv5te/OP_IPUT_WIDE.S */
7253    /* iput-wide vA, vB, field@CCCC */
7254    mov     r0, rINST, lsr #12          @ r0<- B
7255    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7256    FETCH(r1, 1)                        @ r1<- field ref CCCC
7257    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7258    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7259    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7260    cmp     r0, #0                      @ is resolved entry null?
7261    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72628:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7263    EXPORT_PC()                         @ resolve() could throw
7264    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7265    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7266    cmp     r0, #0                      @ success?
7267    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7268    b       common_exceptionThrown
7269
7270
7271/* ------------------------------ */
7272    .balign 64
7273.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7274/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7275/* File: armv5te/OP_SGET_WIDE.S */
7276    /*
7277     * 64-bit SGET handler.
7278     */
7279    /* sget-wide vAA, field@BBBB */
7280    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7281    FETCH(r1, 1)                        @ r1<- field ref BBBB
7282    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7283    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7284    cmp     r0, #0                      @ is resolved entry null?
7285    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7286.LOP_SGET_WIDE_VOLATILE_finish:
7287    mov     r9, rINST, lsr #8           @ r9<- AA
7288    .if 1
7289    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7290    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7291    .else
7292    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7293    .endif
7294    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7295    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7296    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7298    GOTO_OPCODE(ip)                     @ jump to next instruction
7299
7300
7301/* ------------------------------ */
7302    .balign 64
7303.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7304/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7305/* File: armv5te/OP_SPUT_WIDE.S */
7306    /*
7307     * 64-bit SPUT handler.
7308     */
7309    /* sput-wide vAA, field@BBBB */
7310    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7311    FETCH(r1, 1)                        @ r1<- field ref BBBB
7312    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7313    mov     r9, rINST, lsr #8           @ r9<- AA
7314    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7315    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7316    cmp     r2, #0                      @ is resolved entry null?
7317    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7318.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7319    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7320    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7321    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7322    .if 1
7323    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7324    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7325    .else
7326    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7327    .endif
7328    GOTO_OPCODE(r10)                    @ jump to next instruction
7329
7330
7331/* ------------------------------ */
7332    .balign 64
7333.L_OP_BREAKPOINT: /* 0xec */
7334/* File: armv5te/OP_BREAKPOINT.S */
7335/* File: armv5te/unused.S */
7336    bl      common_abort
7337
7338
7339/* ------------------------------ */
7340    .balign 64
7341.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7342/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7343    /*
7344     * Handle a throw-verification-error instruction.  This throws an
7345     * exception for an error discovered during verification.  The
7346     * exception is indicated by AA, with some detail provided by BBBB.
7347     */
7348    /* op AA, ref@BBBB */
7349    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7350    FETCH(r2, 1)                        @ r2<- BBBB
7351    EXPORT_PC()                         @ export the PC
7352    mov     r1, rINST, lsr #8           @ r1<- AA
7353    bl      dvmThrowVerificationError   @ always throws
7354    b       common_exceptionThrown      @ handle exception
7355
7356/* ------------------------------ */
7357    .balign 64
7358.L_OP_EXECUTE_INLINE: /* 0xee */
7359/* File: armv5te/OP_EXECUTE_INLINE.S */
7360    /*
7361     * Execute a "native inline" instruction.
7362     *
7363     * We need to call an InlineOp4Func:
7364     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7365     *
7366     * The first four args are in r0-r3, pointer to return value storage
7367     * is on the stack.  The function's return value is a flag that tells
7368     * us if an exception was thrown.
7369     */
7370    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7371    FETCH(r10, 1)                       @ r10<- BBBB
7372    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7373    EXPORT_PC()                         @ can throw
7374    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7375    mov     r0, rINST, lsr #12          @ r0<- B
7376    str     r1, [sp]                    @ push &glue->retval
7377    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7378    add     sp, sp, #8                  @ pop stack
7379    cmp     r0, #0                      @ test boolean result of inline
7380    beq     common_exceptionThrown      @ returned false, handle exception
7381    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7382    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7383    GOTO_OPCODE(ip)                     @ jump to next instruction
7384
7385/* ------------------------------ */
7386    .balign 64
7387.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7388/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7389    /*
7390     * Execute a "native inline" instruction, using "/range" semantics.
7391     * Same idea as execute-inline, but we get the args differently.
7392     *
7393     * We need to call an InlineOp4Func:
7394     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7395     *
7396     * The first four args are in r0-r3, pointer to return value storage
7397     * is on the stack.  The function's return value is a flag that tells
7398     * us if an exception was thrown.
7399     */
7400    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7401    FETCH(r10, 1)                       @ r10<- BBBB
7402    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7403    EXPORT_PC()                         @ can throw
7404    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7405    mov     r0, rINST, lsr #8           @ r0<- AA
7406    str     r1, [sp]                    @ push &glue->retval
7407    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7408    add     sp, sp, #8                  @ pop stack
7409    cmp     r0, #0                      @ test boolean result of inline
7410    beq     common_exceptionThrown      @ returned false, handle exception
7411    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7413    GOTO_OPCODE(ip)                     @ jump to next instruction
7414
7415/* ------------------------------ */
7416    .balign 64
7417.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7418/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7419    /*
7420     * invoke-direct-empty is a no-op in a "standard" interpreter.
7421     */
7422    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7423    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7424    GOTO_OPCODE(ip)                     @ execute it
7425
7426/* ------------------------------ */
7427    .balign 64
7428.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7429/* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7430    SMP_DMB_ST
7431    b       common_returnFromMethod
7432
7433/* ------------------------------ */
7434    .balign 64
7435.L_OP_IGET_QUICK: /* 0xf2 */
7436/* File: armv5te/OP_IGET_QUICK.S */
7437    /* For: iget-quick, iget-object-quick */
7438    /* op vA, vB, offset@CCCC */
7439    mov     r2, rINST, lsr #12          @ r2<- B
7440    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7441    FETCH(r1, 1)                        @ r1<- field byte offset
7442    cmp     r3, #0                      @ check object for null
7443    mov     r2, rINST, lsr #8           @ r2<- A(+)
7444    beq     common_errNullObject        @ object was null
7445    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7446    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7447    and     r2, r2, #15
7448    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7449    SET_VREG(r0, r2)                    @ fp[A]<- r0
7450    GOTO_OPCODE(ip)                     @ jump to next instruction
7451
7452/* ------------------------------ */
7453    .balign 64
7454.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7455/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7456    /* iget-wide-quick vA, vB, offset@CCCC */
7457    mov     r2, rINST, lsr #12          @ r2<- B
7458    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7459    FETCH(ip, 1)                        @ ip<- field byte offset
7460    cmp     r3, #0                      @ check object for null
7461    mov     r2, rINST, lsr #8           @ r2<- A(+)
7462    beq     common_errNullObject        @ object was null
7463    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7464    and     r2, r2, #15
7465    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7466    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7467    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7468    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7469    GOTO_OPCODE(ip)                     @ jump to next instruction
7470
7471/* ------------------------------ */
7472    .balign 64
7473.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7474/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7475/* File: armv5te/OP_IGET_QUICK.S */
7476    /* For: iget-quick, iget-object-quick */
7477    /* op vA, vB, offset@CCCC */
7478    mov     r2, rINST, lsr #12          @ r2<- B
7479    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7480    FETCH(r1, 1)                        @ r1<- field byte offset
7481    cmp     r3, #0                      @ check object for null
7482    mov     r2, rINST, lsr #8           @ r2<- A(+)
7483    beq     common_errNullObject        @ object was null
7484    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7485    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7486    and     r2, r2, #15
7487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7488    SET_VREG(r0, r2)                    @ fp[A]<- r0
7489    GOTO_OPCODE(ip)                     @ jump to next instruction
7490
7491
7492/* ------------------------------ */
7493    .balign 64
7494.L_OP_IPUT_QUICK: /* 0xf5 */
7495/* File: armv5te/OP_IPUT_QUICK.S */
7496    /* For: iput-quick */
7497    /* op vA, vB, offset@CCCC */
7498    mov     r2, rINST, lsr #12          @ r2<- B
7499    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7500    FETCH(r1, 1)                        @ r1<- field byte offset
7501    cmp     r3, #0                      @ check object for null
7502    mov     r2, rINST, lsr #8           @ r2<- A(+)
7503    beq     common_errNullObject        @ object was null
7504    and     r2, r2, #15
7505    GET_VREG(r0, r2)                    @ r0<- fp[A]
7506    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7507    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7509    GOTO_OPCODE(ip)                     @ jump to next instruction
7510
7511/* ------------------------------ */
7512    .balign 64
7513.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7514/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7515    /* iput-wide-quick vA, vB, offset@CCCC */
7516    mov     r0, rINST, lsr #8           @ r0<- A(+)
7517    mov     r1, rINST, lsr #12          @ r1<- B
7518    and     r0, r0, #15
7519    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7520    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7521    cmp     r2, #0                      @ check object for null
7522    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7523    beq     common_errNullObject        @ object was null
7524    FETCH(r3, 1)                        @ r3<- field byte offset
7525    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7526    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7527    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7528    GOTO_OPCODE(ip)                     @ jump to next instruction
7529
7530/* ------------------------------ */
7531    .balign 64
7532.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7533/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7534    /* For: iput-object-quick */
7535    /* op vA, vB, offset@CCCC */
7536    mov     r2, rINST, lsr #12          @ r2<- B
7537    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7538    FETCH(r1, 1)                        @ r1<- field byte offset
7539    cmp     r3, #0                      @ check object for null
7540    mov     r2, rINST, lsr #8           @ r2<- A(+)
7541    beq     common_errNullObject        @ object was null
7542    and     r2, r2, #15
7543    GET_VREG(r0, r2)                    @ r0<- fp[A]
7544    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7545    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7546    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7547    cmp     r0, #0
7548    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7550    GOTO_OPCODE(ip)                     @ jump to next instruction
7551
7552/* ------------------------------ */
7553    .balign 64
7554.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7555/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7556    /*
7557     * Handle an optimized virtual method call.
7558     *
7559     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7560     */
7561    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7562    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7563    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7564    FETCH(r1, 1)                        @ r1<- BBBB
7565    .if     (!0)
7566    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7567    .endif
7568    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7569    cmp     r2, #0                      @ is "this" null?
7570    beq     common_errNullObject        @ null "this", throw exception
7571    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7572    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7573    EXPORT_PC()                         @ invoke must export
7574    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7575    bl      common_invokeMethodNoRange @ continue on
7576
7577/* ------------------------------ */
7578    .balign 64
7579.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7580/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7581/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7582    /*
7583     * Handle an optimized virtual method call.
7584     *
7585     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7586     */
7587    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7588    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7589    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7590    FETCH(r1, 1)                        @ r1<- BBBB
7591    .if     (!1)
7592    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7593    .endif
7594    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7595    cmp     r2, #0                      @ is "this" null?
7596    beq     common_errNullObject        @ null "this", throw exception
7597    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7598    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7599    EXPORT_PC()                         @ invoke must export
7600    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7601    bl      common_invokeMethodRange @ continue on
7602
7603
7604/* ------------------------------ */
7605    .balign 64
7606.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7607/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7608    /*
7609     * Handle an optimized "super" method call.
7610     *
7611     * for: [opt] invoke-super-quick, invoke-super-quick/range
7612     */
7613    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7614    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7615    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7616    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7617    .if     (!0)
7618    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7619    .endif
7620    FETCH(r1, 1)                        @ r1<- BBBB
7621    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7622    EXPORT_PC()                         @ must export for invoke
7623    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7624    GET_VREG(r3, r10)                   @ r3<- "this"
7625    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7626    cmp     r3, #0                      @ null "this" ref?
7627    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7628    beq     common_errNullObject        @ "this" is null, throw exception
7629    bl      common_invokeMethodNoRange @ continue on
7630
7631/* ------------------------------ */
7632    .balign 64
7633.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7634/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7635/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7636    /*
7637     * Handle an optimized "super" method call.
7638     *
7639     * for: [opt] invoke-super-quick, invoke-super-quick/range
7640     */
7641    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7642    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7643    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7644    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7645    .if     (!1)
7646    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7647    .endif
7648    FETCH(r1, 1)                        @ r1<- BBBB
7649    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7650    EXPORT_PC()                         @ must export for invoke
7651    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7652    GET_VREG(r3, r10)                   @ r3<- "this"
7653    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7654    cmp     r3, #0                      @ null "this" ref?
7655    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7656    beq     common_errNullObject        @ "this" is null, throw exception
7657    bl      common_invokeMethodRange @ continue on
7658
7659
7660/* ------------------------------ */
7661    .balign 64
7662.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7663/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7664/* File: armv5te/OP_IPUT_OBJECT.S */
7665    /*
7666     * 32-bit instance field put.
7667     *
7668     * for: iput-object, iput-object-volatile
7669     */
7670    /* op vA, vB, field@CCCC */
7671    mov     r0, rINST, lsr #12          @ r0<- B
7672    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7673    FETCH(r1, 1)                        @ r1<- field ref CCCC
7674    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7675    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7676    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7677    cmp     r0, #0                      @ is resolved entry null?
7678    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76798:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7680    EXPORT_PC()                         @ resolve() could throw
7681    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7682    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7683    cmp     r0, #0                      @ success?
7684    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7685    b       common_exceptionThrown
7686
7687
7688/* ------------------------------ */
7689    .balign 64
7690.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7691/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7692/* File: armv5te/OP_SGET.S */
7693    /*
7694     * General 32-bit SGET handler.
7695     *
7696     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7697     */
7698    /* op vAA, field@BBBB */
7699    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7700    FETCH(r1, 1)                        @ r1<- field ref BBBB
7701    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7702    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7703    cmp     r0, #0                      @ is resolved entry null?
7704    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7705.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7706    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7707    SMP_DMB                            @ acquiring load
7708    mov     r2, rINST, lsr #8           @ r2<- AA
7709    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7710    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7712    GOTO_OPCODE(ip)                     @ jump to next instruction
7713
7714
7715/* ------------------------------ */
7716    .balign 64
7717.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7718/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7719/* File: armv5te/OP_SPUT_OBJECT.S */
7720    /*
7721     * 32-bit SPUT handler for objects
7722     *
7723     * for: sput-object, sput-object-volatile
7724     */
7725    /* op vAA, field@BBBB */
7726    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7727    FETCH(r1, 1)                        @ r1<- field ref BBBB
7728    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7729    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7730    cmp     r0, #0                      @ is resolved entry null?
7731    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7732    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7733    EXPORT_PC()                         @ resolve() could throw, so export now
7734    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7735    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7736    cmp     r0, #0                      @ success?
7737    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7738    b       common_exceptionThrown      @ no, handle exception
7739
7740
7741
7742/* ------------------------------ */
7743    .balign 64
7744.L_OP_UNUSED_FF: /* 0xff */
7745/* File: armv5te/OP_UNUSED_FF.S */
7746/* File: armv5te/unused.S */
7747    bl      common_abort
7748
7749
7750
7751    .balign 64
7752    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7753    .global dvmAsmInstructionEnd
7754dvmAsmInstructionEnd:
7755
7756/*
7757 * ===========================================================================
7758 *  Sister implementations
7759 * ===========================================================================
7760 */
7761    .global dvmAsmSisterStart
7762    .type   dvmAsmSisterStart, %function
7763    .text
7764    .balign 4
7765dvmAsmSisterStart:
7766
7767/* continuation for OP_CONST_STRING */
7768
7769    /*
7770     * Continuation if the String has not yet been resolved.
7771     *  r1: BBBB (String ref)
7772     *  r9: target register
7773     */
7774.LOP_CONST_STRING_resolve:
7775    EXPORT_PC()
7776    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7777    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7778    bl      dvmResolveString            @ r0<- String reference
7779    cmp     r0, #0                      @ failed?
7780    beq     common_exceptionThrown      @ yup, handle the exception
7781    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7782    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7783    SET_VREG(r0, r9)                    @ vAA<- r0
7784    GOTO_OPCODE(ip)                     @ jump to next instruction
7785
7786/* continuation for OP_CONST_STRING_JUMBO */
7787
7788    /*
7789     * Continuation if the String has not yet been resolved.
7790     *  r1: BBBBBBBB (String ref)
7791     *  r9: target register
7792     */
7793.LOP_CONST_STRING_JUMBO_resolve:
7794    EXPORT_PC()
7795    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7796    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7797    bl      dvmResolveString            @ r0<- String reference
7798    cmp     r0, #0                      @ failed?
7799    beq     common_exceptionThrown      @ yup, handle the exception
7800    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7802    SET_VREG(r0, r9)                    @ vAA<- r0
7803    GOTO_OPCODE(ip)                     @ jump to next instruction
7804
7805/* continuation for OP_CONST_CLASS */
7806
7807    /*
7808     * Continuation if the Class has not yet been resolved.
7809     *  r1: BBBB (Class ref)
7810     *  r9: target register
7811     */
7812.LOP_CONST_CLASS_resolve:
7813    EXPORT_PC()
7814    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7815    mov     r2, #1                      @ r2<- true
7816    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7817    bl      dvmResolveClass             @ r0<- Class reference
7818    cmp     r0, #0                      @ failed?
7819    beq     common_exceptionThrown      @ yup, handle the exception
7820    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7822    SET_VREG(r0, r9)                    @ vAA<- r0
7823    GOTO_OPCODE(ip)                     @ jump to next instruction
7824
7825/* continuation for OP_CHECK_CAST */
7826
7827    /*
7828     * Trivial test failed, need to perform full check.  This is common.
7829     *  r0 holds obj->clazz
7830     *  r1 holds class resolved from BBBB
7831     *  r9 holds object
7832     */
7833.LOP_CHECK_CAST_fullcheck:
7834    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7835    cmp     r0, #0                      @ failed?
7836    bne     .LOP_CHECK_CAST_okay            @ no, success
7837
7838    @ A cast has failed.  We need to throw a ClassCastException with the
7839    @ class of the object that failed to be cast.
7840    EXPORT_PC()                         @ about to throw
7841    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7842    ldr     r0, .LstrClassCastExceptionPtr
7843    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7844    bl      dvmThrowExceptionWithClassMessage
7845    b       common_exceptionThrown
7846
7847    /*
7848     * Resolution required.  This is the least-likely path.
7849     *
7850     *  r2 holds BBBB
7851     *  r9 holds object
7852     */
7853.LOP_CHECK_CAST_resolve:
7854    EXPORT_PC()                         @ resolve() could throw
7855    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7856    mov     r1, r2                      @ r1<- BBBB
7857    mov     r2, #0                      @ r2<- false
7858    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7859    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7860    cmp     r0, #0                      @ got null?
7861    beq     common_exceptionThrown      @ yes, handle exception
7862    mov     r1, r0                      @ r1<- class resolved from BBB
7863    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7864    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7865
7866.LstrClassCastExceptionPtr:
7867    .word   .LstrClassCastException
7868
7869/* continuation for OP_INSTANCE_OF */
7870
7871    /*
7872     * Trivial test failed, need to perform full check.  This is common.
7873     *  r0 holds obj->clazz
7874     *  r1 holds class resolved from BBBB
7875     *  r9 holds A
7876     */
7877.LOP_INSTANCE_OF_fullcheck:
7878    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7879    @ fall through to OP_INSTANCE_OF_store
7880
7881    /*
7882     * r0 holds boolean result
7883     * r9 holds A
7884     */
7885.LOP_INSTANCE_OF_store:
7886    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7887    SET_VREG(r0, r9)                    @ vA<- r0
7888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7889    GOTO_OPCODE(ip)                     @ jump to next instruction
7890
7891    /*
7892     * Trivial test succeeded, save and bail.
7893     *  r9 holds A
7894     */
7895.LOP_INSTANCE_OF_trivial:
7896    mov     r0, #1                      @ indicate success
7897    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7898    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7899    SET_VREG(r0, r9)                    @ vA<- r0
7900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7901    GOTO_OPCODE(ip)                     @ jump to next instruction
7902
7903    /*
7904     * Resolution required.  This is the least-likely path.
7905     *
7906     *  r3 holds BBBB
7907     *  r9 holds A
7908     */
7909.LOP_INSTANCE_OF_resolve:
7910    EXPORT_PC()                         @ resolve() could throw
7911    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7912    mov     r1, r3                      @ r1<- BBBB
7913    mov     r2, #1                      @ r2<- true
7914    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7915    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7916    cmp     r0, #0                      @ got null?
7917    beq     common_exceptionThrown      @ yes, handle exception
7918    mov     r1, r0                      @ r1<- class resolved from BBB
7919    mov     r3, rINST, lsr #12          @ r3<- B
7920    GET_VREG(r0, r3)                    @ r0<- vB (object)
7921    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7922    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7923
7924/* continuation for OP_NEW_INSTANCE */
7925
7926    .balign 32                          @ minimize cache lines
7927.LOP_NEW_INSTANCE_finish: @ r0=new object
7928    mov     r3, rINST, lsr #8           @ r3<- AA
7929    cmp     r0, #0                      @ failed?
7930    beq     common_exceptionThrown      @ yes, handle the exception
7931    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7932    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7933    SET_VREG(r0, r3)                    @ vAA<- r0
7934    GOTO_OPCODE(ip)                     @ jump to next instruction
7935
7936    /*
7937     * Class initialization required.
7938     *
7939     *  r0 holds class object
7940     */
7941.LOP_NEW_INSTANCE_needinit:
7942    mov     r9, r0                      @ save r0
7943    bl      dvmInitClass                @ initialize class
7944    cmp     r0, #0                      @ check boolean result
7945    mov     r0, r9                      @ restore r0
7946    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7947    b       common_exceptionThrown      @ failed, deal with init exception
7948
7949    /*
7950     * Resolution required.  This is the least-likely path.
7951     *
7952     *  r1 holds BBBB
7953     */
7954.LOP_NEW_INSTANCE_resolve:
7955    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7956    mov     r2, #0                      @ r2<- false
7957    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7958    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7959    cmp     r0, #0                      @ got null?
7960    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7961    b       common_exceptionThrown      @ yes, handle exception
7962
7963.LstrInstantiationErrorPtr:
7964    .word   .LstrInstantiationError
7965
7966/* continuation for OP_NEW_ARRAY */
7967
7968
7969    /*
7970     * Resolve class.  (This is an uncommon case.)
7971     *
7972     *  r1 holds array length
7973     *  r2 holds class ref CCCC
7974     */
7975.LOP_NEW_ARRAY_resolve:
7976    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7977    mov     r9, r1                      @ r9<- length (save)
7978    mov     r1, r2                      @ r1<- CCCC
7979    mov     r2, #0                      @ r2<- false
7980    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7981    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7982    cmp     r0, #0                      @ got null?
7983    mov     r1, r9                      @ r1<- length (restore)
7984    beq     common_exceptionThrown      @ yes, handle exception
7985    @ fall through to OP_NEW_ARRAY_finish
7986
7987    /*
7988     * Finish allocation.
7989     *
7990     *  r0 holds class
7991     *  r1 holds array length
7992     */
7993.LOP_NEW_ARRAY_finish:
7994    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7995    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7996    cmp     r0, #0                      @ failed?
7997    mov     r2, rINST, lsr #8           @ r2<- A+
7998    beq     common_exceptionThrown      @ yes, handle the exception
7999    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8000    and     r2, r2, #15                 @ r2<- A
8001    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8002    SET_VREG(r0, r2)                    @ vA<- r0
8003    GOTO_OPCODE(ip)                     @ jump to next instruction
8004
8005/* continuation for OP_FILLED_NEW_ARRAY */
8006
8007    /*
8008     * On entry:
8009     *  r0 holds array class
8010     *  r10 holds AA or BA
8011     */
8012.LOP_FILLED_NEW_ARRAY_continue:
8013    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8014    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8015    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8016    .if     0
8017    mov     r1, r10                     @ r1<- AA (length)
8018    .else
8019    mov     r1, r10, lsr #4             @ r1<- B (length)
8020    .endif
8021    cmp     rINST, #'I'                 @ array of ints?
8022    cmpne   rINST, #'L'                 @ array of objects?
8023    cmpne   rINST, #'['                 @ array of arrays?
8024    mov     r9, r1                      @ save length in r9
8025    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8026    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8027    cmp     r0, #0                      @ null return?
8028    beq     common_exceptionThrown      @ alloc failed, handle exception
8029
8030    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8031    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8032    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8033    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8034    subs    r9, r9, #1                  @ length--, check for neg
8035    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8036    bmi     2f                          @ was zero, bail
8037
8038    @ copy values from registers into the array
8039    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8040    .if     0
8041    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80421:  ldr     r3, [r2], #4                @ r3<- *r2++
8043    subs    r9, r9, #1                  @ count--
8044    str     r3, [r0], #4                @ *contents++ = vX
8045    bpl     1b
8046    @ continue at 2
8047    .else
8048    cmp     r9, #4                      @ length was initially 5?
8049    and     r2, r10, #15                @ r2<- A
8050    bne     1f                          @ <= 4 args, branch
8051    GET_VREG(r3, r2)                    @ r3<- vA
8052    sub     r9, r9, #1                  @ count--
8053    str     r3, [r0, #16]               @ contents[4] = vA
80541:  and     r2, r1, #15                 @ r2<- F/E/D/C
8055    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8056    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8057    subs    r9, r9, #1                  @ count--
8058    str     r3, [r0], #4                @ *contents++ = vX
8059    bpl     1b
8060    @ continue at 2
8061    .endif
8062
80632:
8064    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8065    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8066    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8067    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8068    cmp     r1, #'I'                         @ Is int array?
8069    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8070    GOTO_OPCODE(ip)                          @ execute it
8071
8072    /*
8073     * Throw an exception indicating that we have not implemented this
8074     * mode of filled-new-array.
8075     */
8076.LOP_FILLED_NEW_ARRAY_notimpl:
8077    ldr     r0, .L_strInternalError
8078    ldr     r1, .L_strFilledNewArrayNotImpl
8079    bl      dvmThrowException
8080    b       common_exceptionThrown
8081
8082    .if     (!0)                 @ define in one or the other, not both
8083.L_strFilledNewArrayNotImpl:
8084    .word   .LstrFilledNewArrayNotImpl
8085.L_strInternalError:
8086    .word   .LstrInternalError
8087    .endif
8088
8089/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8090
8091    /*
8092     * On entry:
8093     *  r0 holds array class
8094     *  r10 holds AA or BA
8095     */
8096.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8097    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8098    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8099    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8100    .if     1
8101    mov     r1, r10                     @ r1<- AA (length)
8102    .else
8103    mov     r1, r10, lsr #4             @ r1<- B (length)
8104    .endif
8105    cmp     rINST, #'I'                 @ array of ints?
8106    cmpne   rINST, #'L'                 @ array of objects?
8107    cmpne   rINST, #'['                 @ array of arrays?
8108    mov     r9, r1                      @ save length in r9
8109    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8110    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8111    cmp     r0, #0                      @ null return?
8112    beq     common_exceptionThrown      @ alloc failed, handle exception
8113
8114    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8115    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8116    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8117    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8118    subs    r9, r9, #1                  @ length--, check for neg
8119    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8120    bmi     2f                          @ was zero, bail
8121
8122    @ copy values from registers into the array
8123    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8124    .if     1
8125    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81261:  ldr     r3, [r2], #4                @ r3<- *r2++
8127    subs    r9, r9, #1                  @ count--
8128    str     r3, [r0], #4                @ *contents++ = vX
8129    bpl     1b
8130    @ continue at 2
8131    .else
8132    cmp     r9, #4                      @ length was initially 5?
8133    and     r2, r10, #15                @ r2<- A
8134    bne     1f                          @ <= 4 args, branch
8135    GET_VREG(r3, r2)                    @ r3<- vA
8136    sub     r9, r9, #1                  @ count--
8137    str     r3, [r0, #16]               @ contents[4] = vA
81381:  and     r2, r1, #15                 @ r2<- F/E/D/C
8139    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8140    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8141    subs    r9, r9, #1                  @ count--
8142    str     r3, [r0], #4                @ *contents++ = vX
8143    bpl     1b
8144    @ continue at 2
8145    .endif
8146
81472:
8148    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8149    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8150    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8151    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8152    cmp     r1, #'I'                         @ Is int array?
8153    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8154    GOTO_OPCODE(ip)                          @ execute it
8155
8156    /*
8157     * Throw an exception indicating that we have not implemented this
8158     * mode of filled-new-array.
8159     */
8160.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8161    ldr     r0, .L_strInternalError
8162    ldr     r1, .L_strFilledNewArrayNotImpl
8163    bl      dvmThrowException
8164    b       common_exceptionThrown
8165
8166    .if     (!1)                 @ define in one or the other, not both
8167.L_strFilledNewArrayNotImpl:
8168    .word   .LstrFilledNewArrayNotImpl
8169.L_strInternalError:
8170    .word   .LstrInternalError
8171    .endif
8172
8173/* continuation for OP_CMPL_FLOAT */
8174.LOP_CMPL_FLOAT_finish:
8175    SET_VREG(r0, r9)                    @ vAA<- r0
8176    GOTO_OPCODE(ip)                     @ jump to next instruction
8177
8178/* continuation for OP_CMPG_FLOAT */
8179.LOP_CMPG_FLOAT_finish:
8180    SET_VREG(r0, r9)                    @ vAA<- r0
8181    GOTO_OPCODE(ip)                     @ jump to next instruction
8182
8183/* continuation for OP_CMPL_DOUBLE */
8184.LOP_CMPL_DOUBLE_finish:
8185    SET_VREG(r0, r9)                    @ vAA<- r0
8186    GOTO_OPCODE(ip)                     @ jump to next instruction
8187
8188/* continuation for OP_CMPG_DOUBLE */
8189.LOP_CMPG_DOUBLE_finish:
8190    SET_VREG(r0, r9)                    @ vAA<- r0
8191    GOTO_OPCODE(ip)                     @ jump to next instruction
8192
8193/* continuation for OP_CMP_LONG */
8194
8195.LOP_CMP_LONG_less:
8196    mvn     r1, #0                      @ r1<- -1
8197    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8198    @ instead, we just replicate the tail end.
8199    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8200    SET_VREG(r1, r9)                    @ vAA<- r1
8201    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8202    GOTO_OPCODE(ip)                     @ jump to next instruction
8203
8204.LOP_CMP_LONG_greater:
8205    mov     r1, #1                      @ r1<- 1
8206    @ fall through to _finish
8207
8208.LOP_CMP_LONG_finish:
8209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8210    SET_VREG(r1, r9)                    @ vAA<- r1
8211    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8212    GOTO_OPCODE(ip)                     @ jump to next instruction
8213
8214/* continuation for OP_AGET_WIDE */
8215
8216.LOP_AGET_WIDE_finish:
8217    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8218    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8219    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8221    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8222    GOTO_OPCODE(ip)                     @ jump to next instruction
8223
8224/* continuation for OP_APUT_WIDE */
8225
8226.LOP_APUT_WIDE_finish:
8227    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8228    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8230    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8231    GOTO_OPCODE(ip)                     @ jump to next instruction
8232
8233/* continuation for OP_APUT_OBJECT */
8234    /*
8235     * On entry:
8236     *  rINST = vBB (arrayObj)
8237     *  r9 = vAA (obj)
8238     *  r10 = offset into array (vBB + vCC * width)
8239     */
8240.LOP_APUT_OBJECT_finish:
8241    cmp     r9, #0                      @ storing null reference?
8242    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8243    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8244    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8245    bl      dvmCanPutArrayElement       @ test object type vs. array type
8246    cmp     r0, #0                      @ okay?
8247    beq     common_errArrayStore        @ no
8248    mov     r1, rINST                   @ r1<- arrayObj
8249    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8250    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8251    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8252    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8253    str     r9, [r10]                   @ vBB[vCC]<- vAA
8254    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8255    GOTO_OPCODE(ip)                     @ jump to next instruction
8256.LOP_APUT_OBJECT_skip_check:
8257    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8259    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8260    GOTO_OPCODE(ip)                     @ jump to next instruction
8261
8262/* continuation for OP_IGET */
8263
8264    /*
8265     * Currently:
8266     *  r0 holds resolved field
8267     *  r9 holds object
8268     */
8269.LOP_IGET_finish:
8270    @bl      common_squeak0
8271    cmp     r9, #0                      @ check object for null
8272    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8273    beq     common_errNullObject        @ object was null
8274    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8275    @ no-op                             @ acquiring load
8276    mov     r2, rINST, lsr #8           @ r2<- A+
8277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8278    and     r2, r2, #15                 @ r2<- A
8279    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8280    SET_VREG(r0, r2)                    @ fp[A]<- r0
8281    GOTO_OPCODE(ip)                     @ jump to next instruction
8282
8283/* continuation for OP_IGET_WIDE */
8284
8285    /*
8286     * Currently:
8287     *  r0 holds resolved field
8288     *  r9 holds object
8289     */
8290.LOP_IGET_WIDE_finish:
8291    cmp     r9, #0                      @ check object for null
8292    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8293    beq     common_errNullObject        @ object was null
8294    .if     0
8295    add     r0, r9, r3                  @ r0<- address of field
8296    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8297    .else
8298    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8299    .endif
8300    mov     r2, rINST, lsr #8           @ r2<- A+
8301    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8302    and     r2, r2, #15                 @ r2<- A
8303    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8305    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8306    GOTO_OPCODE(ip)                     @ jump to next instruction
8307
8308/* continuation for OP_IGET_OBJECT */
8309
8310    /*
8311     * Currently:
8312     *  r0 holds resolved field
8313     *  r9 holds object
8314     */
8315.LOP_IGET_OBJECT_finish:
8316    @bl      common_squeak0
8317    cmp     r9, #0                      @ check object for null
8318    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8319    beq     common_errNullObject        @ object was null
8320    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8321    @ no-op                             @ acquiring load
8322    mov     r2, rINST, lsr #8           @ r2<- A+
8323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8324    and     r2, r2, #15                 @ r2<- A
8325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8326    SET_VREG(r0, r2)                    @ fp[A]<- r0
8327    GOTO_OPCODE(ip)                     @ jump to next instruction
8328
8329/* continuation for OP_IGET_BOOLEAN */
8330
8331    /*
8332     * Currently:
8333     *  r0 holds resolved field
8334     *  r9 holds object
8335     */
8336.LOP_IGET_BOOLEAN_finish:
8337    @bl      common_squeak1
8338    cmp     r9, #0                      @ check object for null
8339    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8340    beq     common_errNullObject        @ object was null
8341    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8342    @ no-op                             @ acquiring load
8343    mov     r2, rINST, lsr #8           @ r2<- A+
8344    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8345    and     r2, r2, #15                 @ r2<- A
8346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8347    SET_VREG(r0, r2)                    @ fp[A]<- r0
8348    GOTO_OPCODE(ip)                     @ jump to next instruction
8349
8350/* continuation for OP_IGET_BYTE */
8351
8352    /*
8353     * Currently:
8354     *  r0 holds resolved field
8355     *  r9 holds object
8356     */
8357.LOP_IGET_BYTE_finish:
8358    @bl      common_squeak2
8359    cmp     r9, #0                      @ check object for null
8360    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8361    beq     common_errNullObject        @ object was null
8362    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8363    @ no-op                             @ acquiring load
8364    mov     r2, rINST, lsr #8           @ r2<- A+
8365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8366    and     r2, r2, #15                 @ r2<- A
8367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8368    SET_VREG(r0, r2)                    @ fp[A]<- r0
8369    GOTO_OPCODE(ip)                     @ jump to next instruction
8370
8371/* continuation for OP_IGET_CHAR */
8372
8373    /*
8374     * Currently:
8375     *  r0 holds resolved field
8376     *  r9 holds object
8377     */
8378.LOP_IGET_CHAR_finish:
8379    @bl      common_squeak3
8380    cmp     r9, #0                      @ check object for null
8381    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8382    beq     common_errNullObject        @ object was null
8383    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8384    @ no-op                             @ acquiring load
8385    mov     r2, rINST, lsr #8           @ r2<- A+
8386    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8387    and     r2, r2, #15                 @ r2<- A
8388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8389    SET_VREG(r0, r2)                    @ fp[A]<- r0
8390    GOTO_OPCODE(ip)                     @ jump to next instruction
8391
8392/* continuation for OP_IGET_SHORT */
8393
8394    /*
8395     * Currently:
8396     *  r0 holds resolved field
8397     *  r9 holds object
8398     */
8399.LOP_IGET_SHORT_finish:
8400    @bl      common_squeak4
8401    cmp     r9, #0                      @ check object for null
8402    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8403    beq     common_errNullObject        @ object was null
8404    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8405    @ no-op                             @ acquiring load
8406    mov     r2, rINST, lsr #8           @ r2<- A+
8407    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8408    and     r2, r2, #15                 @ r2<- A
8409    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8410    SET_VREG(r0, r2)                    @ fp[A]<- r0
8411    GOTO_OPCODE(ip)                     @ jump to next instruction
8412
8413/* continuation for OP_IPUT */
8414
8415    /*
8416     * Currently:
8417     *  r0 holds resolved field
8418     *  r9 holds object
8419     */
8420.LOP_IPUT_finish:
8421    @bl      common_squeak0
8422    mov     r1, rINST, lsr #8           @ r1<- A+
8423    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8424    and     r1, r1, #15                 @ r1<- A
8425    cmp     r9, #0                      @ check object for null
8426    GET_VREG(r0, r1)                    @ r0<- fp[A]
8427    beq     common_errNullObject        @ object was null
8428    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8429    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8430    @ no-op                             @ releasing store
8431    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8432    GOTO_OPCODE(ip)                     @ jump to next instruction
8433
8434/* continuation for OP_IPUT_WIDE */
8435
8436    /*
8437     * Currently:
8438     *  r0 holds resolved field
8439     *  r9 holds object
8440     */
8441.LOP_IPUT_WIDE_finish:
8442    mov     r2, rINST, lsr #8           @ r2<- A+
8443    cmp     r9, #0                      @ check object for null
8444    and     r2, r2, #15                 @ r2<- A
8445    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8446    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8447    beq     common_errNullObject        @ object was null
8448    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8449    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8450    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8451    .if     0
8452    add     r2, r9, r3                  @ r2<- target address
8453    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8454    .else
8455    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8456    .endif
8457    GOTO_OPCODE(r10)                    @ jump to next instruction
8458
8459/* continuation for OP_IPUT_OBJECT */
8460
8461    /*
8462     * Currently:
8463     *  r0 holds resolved field
8464     *  r9 holds object
8465     */
8466.LOP_IPUT_OBJECT_finish:
8467    @bl      common_squeak0
8468    mov     r1, rINST, lsr #8           @ r1<- A+
8469    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8470    and     r1, r1, #15                 @ r1<- A
8471    cmp     r9, #0                      @ check object for null
8472    GET_VREG(r0, r1)                    @ r0<- fp[A]
8473    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8474    beq     common_errNullObject        @ object was null
8475    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8476    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8477    @ no-op                             @ releasing store
8478    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
8479    cmp     r0, #0                      @ stored a null reference?
8480    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8481    GOTO_OPCODE(ip)                     @ jump to next instruction
8482
8483/* continuation for OP_IPUT_BOOLEAN */
8484
8485    /*
8486     * Currently:
8487     *  r0 holds resolved field
8488     *  r9 holds object
8489     */
8490.LOP_IPUT_BOOLEAN_finish:
8491    @bl      common_squeak1
8492    mov     r1, rINST, lsr #8           @ r1<- A+
8493    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8494    and     r1, r1, #15                 @ r1<- A
8495    cmp     r9, #0                      @ check object for null
8496    GET_VREG(r0, r1)                    @ r0<- fp[A]
8497    beq     common_errNullObject        @ object was null
8498    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8499    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8500    @ no-op                             @ releasing store
8501    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8502    GOTO_OPCODE(ip)                     @ jump to next instruction
8503
8504/* continuation for OP_IPUT_BYTE */
8505
8506    /*
8507     * Currently:
8508     *  r0 holds resolved field
8509     *  r9 holds object
8510     */
8511.LOP_IPUT_BYTE_finish:
8512    @bl      common_squeak2
8513    mov     r1, rINST, lsr #8           @ r1<- A+
8514    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8515    and     r1, r1, #15                 @ r1<- A
8516    cmp     r9, #0                      @ check object for null
8517    GET_VREG(r0, r1)                    @ r0<- fp[A]
8518    beq     common_errNullObject        @ object was null
8519    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8521    @ no-op                             @ releasing store
8522    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8523    GOTO_OPCODE(ip)                     @ jump to next instruction
8524
8525/* continuation for OP_IPUT_CHAR */
8526
8527    /*
8528     * Currently:
8529     *  r0 holds resolved field
8530     *  r9 holds object
8531     */
8532.LOP_IPUT_CHAR_finish:
8533    @bl      common_squeak3
8534    mov     r1, rINST, lsr #8           @ r1<- A+
8535    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8536    and     r1, r1, #15                 @ r1<- A
8537    cmp     r9, #0                      @ check object for null
8538    GET_VREG(r0, r1)                    @ r0<- fp[A]
8539    beq     common_errNullObject        @ object was null
8540    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8541    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8542    @ no-op                             @ releasing store
8543    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8544    GOTO_OPCODE(ip)                     @ jump to next instruction
8545
8546/* continuation for OP_IPUT_SHORT */
8547
8548    /*
8549     * Currently:
8550     *  r0 holds resolved field
8551     *  r9 holds object
8552     */
8553.LOP_IPUT_SHORT_finish:
8554    @bl      common_squeak4
8555    mov     r1, rINST, lsr #8           @ r1<- A+
8556    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8557    and     r1, r1, #15                 @ r1<- A
8558    cmp     r9, #0                      @ check object for null
8559    GET_VREG(r0, r1)                    @ r0<- fp[A]
8560    beq     common_errNullObject        @ object was null
8561    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8562    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8563    @ no-op                             @ releasing store
8564    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8565    GOTO_OPCODE(ip)                     @ jump to next instruction
8566
8567/* continuation for OP_SGET */
8568
8569    /*
8570     * Continuation if the field has not yet been resolved.
8571     *  r1: BBBB field ref
8572     */
8573.LOP_SGET_resolve:
8574    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8575    EXPORT_PC()                         @ resolve() could throw, so export now
8576    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8577    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8578    cmp     r0, #0                      @ success?
8579    bne     .LOP_SGET_finish          @ yes, finish
8580    b       common_exceptionThrown      @ no, handle exception
8581
8582/* continuation for OP_SGET_WIDE */
8583
8584    /*
8585     * Continuation if the field has not yet been resolved.
8586     *  r1: BBBB field ref
8587     *
8588     * Returns StaticField pointer in r0.
8589     */
8590.LOP_SGET_WIDE_resolve:
8591    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8592    EXPORT_PC()                         @ resolve() could throw, so export now
8593    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8594    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8595    cmp     r0, #0                      @ success?
8596    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8597    b       common_exceptionThrown      @ no, handle exception
8598
8599/* continuation for OP_SGET_OBJECT */
8600
8601    /*
8602     * Continuation if the field has not yet been resolved.
8603     *  r1: BBBB field ref
8604     */
8605.LOP_SGET_OBJECT_resolve:
8606    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8607    EXPORT_PC()                         @ resolve() could throw, so export now
8608    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8609    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8610    cmp     r0, #0                      @ success?
8611    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8612    b       common_exceptionThrown      @ no, handle exception
8613
8614/* continuation for OP_SGET_BOOLEAN */
8615
8616    /*
8617     * Continuation if the field has not yet been resolved.
8618     *  r1: BBBB field ref
8619     */
8620.LOP_SGET_BOOLEAN_resolve:
8621    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8622    EXPORT_PC()                         @ resolve() could throw, so export now
8623    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8624    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8625    cmp     r0, #0                      @ success?
8626    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8627    b       common_exceptionThrown      @ no, handle exception
8628
8629/* continuation for OP_SGET_BYTE */
8630
8631    /*
8632     * Continuation if the field has not yet been resolved.
8633     *  r1: BBBB field ref
8634     */
8635.LOP_SGET_BYTE_resolve:
8636    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8637    EXPORT_PC()                         @ resolve() could throw, so export now
8638    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8639    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8640    cmp     r0, #0                      @ success?
8641    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8642    b       common_exceptionThrown      @ no, handle exception
8643
8644/* continuation for OP_SGET_CHAR */
8645
8646    /*
8647     * Continuation if the field has not yet been resolved.
8648     *  r1: BBBB field ref
8649     */
8650.LOP_SGET_CHAR_resolve:
8651    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8652    EXPORT_PC()                         @ resolve() could throw, so export now
8653    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8654    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8655    cmp     r0, #0                      @ success?
8656    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8657    b       common_exceptionThrown      @ no, handle exception
8658
8659/* continuation for OP_SGET_SHORT */
8660
8661    /*
8662     * Continuation if the field has not yet been resolved.
8663     *  r1: BBBB field ref
8664     */
8665.LOP_SGET_SHORT_resolve:
8666    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8667    EXPORT_PC()                         @ resolve() could throw, so export now
8668    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8669    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8670    cmp     r0, #0                      @ success?
8671    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8672    b       common_exceptionThrown      @ no, handle exception
8673
8674/* continuation for OP_SPUT */
8675
8676    /*
8677     * Continuation if the field has not yet been resolved.
8678     *  r1: BBBB field ref
8679     */
8680.LOP_SPUT_resolve:
8681    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8682    EXPORT_PC()                         @ resolve() could throw, so export now
8683    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8684    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8685    cmp     r0, #0                      @ success?
8686    bne     .LOP_SPUT_finish          @ yes, finish
8687    b       common_exceptionThrown      @ no, handle exception
8688
8689/* continuation for OP_SPUT_WIDE */
8690
8691    /*
8692     * Continuation if the field has not yet been resolved.
8693     *  r1: BBBB field ref
8694     *  r9: &fp[AA]
8695     *
8696     * Returns StaticField pointer in r2.
8697     */
8698.LOP_SPUT_WIDE_resolve:
8699    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8700    EXPORT_PC()                         @ resolve() could throw, so export now
8701    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8702    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8703    cmp     r0, #0                      @ success?
8704    mov     r2, r0                      @ copy to r2
8705    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8706    b       common_exceptionThrown      @ no, handle exception
8707
8708/* continuation for OP_SPUT_OBJECT */
8709.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8710    mov     r2, rINST, lsr #8           @ r2<- AA
8711    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8712    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8713    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8714    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
8715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8716    @ no-op                             @ releasing store
8717    str     r1, [r0, #offStaticField_value]  @ field<- vAA
8718    cmp     r1, #0                      @ stored a null object?
8719    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
8720    GOTO_OPCODE(ip)                     @ jump to next instruction
8721
8722/* continuation for OP_SPUT_BOOLEAN */
8723
8724    /*
8725     * Continuation if the field has not yet been resolved.
8726     *  r1: BBBB field ref
8727     */
8728.LOP_SPUT_BOOLEAN_resolve:
8729    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8730    EXPORT_PC()                         @ resolve() could throw, so export now
8731    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8732    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8733    cmp     r0, #0                      @ success?
8734    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8735    b       common_exceptionThrown      @ no, handle exception
8736
8737/* continuation for OP_SPUT_BYTE */
8738
8739    /*
8740     * Continuation if the field has not yet been resolved.
8741     *  r1: BBBB field ref
8742     */
8743.LOP_SPUT_BYTE_resolve:
8744    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8745    EXPORT_PC()                         @ resolve() could throw, so export now
8746    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8747    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8748    cmp     r0, #0                      @ success?
8749    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8750    b       common_exceptionThrown      @ no, handle exception
8751
8752/* continuation for OP_SPUT_CHAR */
8753
8754    /*
8755     * Continuation if the field has not yet been resolved.
8756     *  r1: BBBB field ref
8757     */
8758.LOP_SPUT_CHAR_resolve:
8759    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8760    EXPORT_PC()                         @ resolve() could throw, so export now
8761    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8762    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8763    cmp     r0, #0                      @ success?
8764    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8765    b       common_exceptionThrown      @ no, handle exception
8766
8767/* continuation for OP_SPUT_SHORT */
8768
8769    /*
8770     * Continuation if the field has not yet been resolved.
8771     *  r1: BBBB field ref
8772     */
8773.LOP_SPUT_SHORT_resolve:
8774    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8775    EXPORT_PC()                         @ resolve() could throw, so export now
8776    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8777    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8778    cmp     r0, #0                      @ success?
8779    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8780    b       common_exceptionThrown      @ no, handle exception
8781
8782/* continuation for OP_INVOKE_VIRTUAL */
8783
8784    /*
8785     * At this point:
8786     *  r0 = resolved base method
8787     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8788     */
8789.LOP_INVOKE_VIRTUAL_continue:
8790    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8791    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8792    cmp     r1, #0                      @ is "this" null?
8793    beq     common_errNullObject        @ null "this", throw exception
8794    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8795    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8796    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8797    bl      common_invokeMethodNoRange @ continue on
8798
8799/* continuation for OP_INVOKE_SUPER */
8800
8801    /*
8802     * At this point:
8803     *  r0 = resolved base method
8804     *  r9 = method->clazz
8805     */
8806.LOP_INVOKE_SUPER_continue:
8807    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8808    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8809    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8810    EXPORT_PC()                         @ must export for invoke
8811    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8812    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8813    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8814    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8815    bl      common_invokeMethodNoRange @ continue on
8816
8817.LOP_INVOKE_SUPER_resolve:
8818    mov     r0, r9                      @ r0<- method->clazz
8819    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8820    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8821    cmp     r0, #0                      @ got null?
8822    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8823    b       common_exceptionThrown      @ yes, handle exception
8824
8825    /*
8826     * Throw a NoSuchMethodError with the method name as the message.
8827     *  r0 = resolved base method
8828     */
8829.LOP_INVOKE_SUPER_nsm:
8830    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8831    b       common_errNoSuchMethod
8832
8833/* continuation for OP_INVOKE_DIRECT */
8834
8835    /*
8836     * On entry:
8837     *  r1 = reference (BBBB or CCCC)
8838     *  r10 = "this" register
8839     */
8840.LOP_INVOKE_DIRECT_resolve:
8841    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8842    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8843    mov     r2, #METHOD_DIRECT          @ resolver method type
8844    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8845    cmp     r0, #0                      @ got null?
8846    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8847    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8848    b       common_exceptionThrown      @ yes, handle exception
8849
8850/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8851
8852    /*
8853     * At this point:
8854     *  r0 = resolved base method
8855     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8856     */
8857.LOP_INVOKE_VIRTUAL_RANGE_continue:
8858    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8859    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8860    cmp     r1, #0                      @ is "this" null?
8861    beq     common_errNullObject        @ null "this", throw exception
8862    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8863    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8864    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8865    bl      common_invokeMethodRange @ continue on
8866
8867/* continuation for OP_INVOKE_SUPER_RANGE */
8868
8869    /*
8870     * At this point:
8871     *  r0 = resolved base method
8872     *  r9 = method->clazz
8873     */
8874.LOP_INVOKE_SUPER_RANGE_continue:
8875    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8876    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8877    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8878    EXPORT_PC()                         @ must export for invoke
8879    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8880    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8881    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8882    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8883    bl      common_invokeMethodRange @ continue on
8884
8885.LOP_INVOKE_SUPER_RANGE_resolve:
8886    mov     r0, r9                      @ r0<- method->clazz
8887    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8888    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8889    cmp     r0, #0                      @ got null?
8890    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8891    b       common_exceptionThrown      @ yes, handle exception
8892
8893    /*
8894     * Throw a NoSuchMethodError with the method name as the message.
8895     *  r0 = resolved base method
8896     */
8897.LOP_INVOKE_SUPER_RANGE_nsm:
8898    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8899    b       common_errNoSuchMethod
8900
8901/* continuation for OP_INVOKE_DIRECT_RANGE */
8902
8903    /*
8904     * On entry:
8905     *  r1 = reference (BBBB or CCCC)
8906     *  r10 = "this" register
8907     */
8908.LOP_INVOKE_DIRECT_RANGE_resolve:
8909    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8910    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8911    mov     r2, #METHOD_DIRECT          @ resolver method type
8912    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8913    cmp     r0, #0                      @ got null?
8914    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8915    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8916    b       common_exceptionThrown      @ yes, handle exception
8917
8918/* continuation for OP_FLOAT_TO_LONG */
8919/*
8920 * Convert the float in r0 to a long in r0/r1.
8921 *
8922 * We have to clip values to long min/max per the specification.  The
8923 * expected common case is a "reasonable" value that converts directly
8924 * to modest integer.  The EABI convert function isn't doing this for us.
8925 */
8926f2l_doconv:
8927    stmfd   sp!, {r4, lr}
8928    mov     r1, #0x5f000000             @ (float)maxlong
8929    mov     r4, r0
8930    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8931    cmp     r0, #0                      @ nonzero == yes
8932    mvnne   r0, #0                      @ return maxlong (7fffffff)
8933    mvnne   r1, #0x80000000
8934    ldmnefd sp!, {r4, pc}
8935
8936    mov     r0, r4                      @ recover arg
8937    mov     r1, #0xdf000000             @ (float)minlong
8938    bl      __aeabi_fcmple              @ is arg <= minlong?
8939    cmp     r0, #0                      @ nonzero == yes
8940    movne   r0, #0                      @ return minlong (80000000)
8941    movne   r1, #0x80000000
8942    ldmnefd sp!, {r4, pc}
8943
8944    mov     r0, r4                      @ recover arg
8945    mov     r1, r4
8946    bl      __aeabi_fcmpeq              @ is arg == self?
8947    cmp     r0, #0                      @ zero == no
8948    moveq   r1, #0                      @ return zero for NaN
8949    ldmeqfd sp!, {r4, pc}
8950
8951    mov     r0, r4                      @ recover arg
8952    bl      __aeabi_f2lz                @ convert float to long
8953    ldmfd   sp!, {r4, pc}
8954
8955/* continuation for OP_DOUBLE_TO_LONG */
8956/*
8957 * Convert the double in r0/r1 to a long in r0/r1.
8958 *
8959 * We have to clip values to long min/max per the specification.  The
8960 * expected common case is a "reasonable" value that converts directly
8961 * to modest integer.  The EABI convert function isn't doing this for us.
8962 */
8963d2l_doconv:
8964    stmfd   sp!, {r4, r5, lr}           @ save regs
8965    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8966    add     r3, #0x00e00000             @  0x43e00000
8967    mov     r2, #0                      @ maxlong, as a double (low word)
8968    sub     sp, sp, #4                  @ align for EABI
8969    mov     r4, r0                      @ save a copy of r0
8970    mov     r5, r1                      @  and r1
8971    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8972    cmp     r0, #0                      @ nonzero == yes
8973    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8974    mvnne   r1, #0x80000000
8975    bne     1f
8976
8977    mov     r0, r4                      @ recover arg
8978    mov     r1, r5
8979    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8980    add     r3, #0x00e00000             @  0xc3e00000
8981    mov     r2, #0                      @ minlong, as a double (low word)
8982    bl      __aeabi_dcmple              @ is arg <= minlong?
8983    cmp     r0, #0                      @ nonzero == yes
8984    movne   r0, #0                      @ return minlong (8000000000000000)
8985    movne   r1, #0x80000000
8986    bne     1f
8987
8988    mov     r0, r4                      @ recover arg
8989    mov     r1, r5
8990    mov     r2, r4                      @ compare against self
8991    mov     r3, r5
8992    bl      __aeabi_dcmpeq              @ is arg == self?
8993    cmp     r0, #0                      @ zero == no
8994    moveq   r1, #0                      @ return zero for NaN
8995    beq     1f
8996
8997    mov     r0, r4                      @ recover arg
8998    mov     r1, r5
8999    bl      __aeabi_d2lz                @ convert double to long
9000
90011:
9002    add     sp, sp, #4
9003    ldmfd   sp!, {r4, r5, pc}
9004
9005/* continuation for OP_MUL_LONG */
9006
9007.LOP_MUL_LONG_finish:
9008    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9009    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9010    GOTO_OPCODE(ip)                     @ jump to next instruction
9011
9012/* continuation for OP_SHL_LONG */
9013
9014.LOP_SHL_LONG_finish:
9015    mov     r0, r0, asl r2              @  r0<- r0 << r2
9016    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9017    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9018    GOTO_OPCODE(ip)                     @ jump to next instruction
9019
9020/* continuation for OP_SHR_LONG */
9021
9022.LOP_SHR_LONG_finish:
9023    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9025    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9026    GOTO_OPCODE(ip)                     @ jump to next instruction
9027
9028/* continuation for OP_USHR_LONG */
9029
9030.LOP_USHR_LONG_finish:
9031    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9032    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9033    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9034    GOTO_OPCODE(ip)                     @ jump to next instruction
9035
9036/* continuation for OP_SHL_LONG_2ADDR */
9037
9038.LOP_SHL_LONG_2ADDR_finish:
9039    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9040    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9041    GOTO_OPCODE(ip)                     @ jump to next instruction
9042
9043/* continuation for OP_SHR_LONG_2ADDR */
9044
9045.LOP_SHR_LONG_2ADDR_finish:
9046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9047    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9048    GOTO_OPCODE(ip)                     @ jump to next instruction
9049
9050/* continuation for OP_USHR_LONG_2ADDR */
9051
9052.LOP_USHR_LONG_2ADDR_finish:
9053    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9054    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9055    GOTO_OPCODE(ip)                     @ jump to next instruction
9056
9057/* continuation for OP_IGET_VOLATILE */
9058
9059    /*
9060     * Currently:
9061     *  r0 holds resolved field
9062     *  r9 holds object
9063     */
9064.LOP_IGET_VOLATILE_finish:
9065    @bl      common_squeak0
9066    cmp     r9, #0                      @ check object for null
9067    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9068    beq     common_errNullObject        @ object was null
9069    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9070    SMP_DMB                            @ acquiring load
9071    mov     r2, rINST, lsr #8           @ r2<- A+
9072    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9073    and     r2, r2, #15                 @ r2<- A
9074    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9075    SET_VREG(r0, r2)                    @ fp[A]<- r0
9076    GOTO_OPCODE(ip)                     @ jump to next instruction
9077
9078/* continuation for OP_IPUT_VOLATILE */
9079
9080    /*
9081     * Currently:
9082     *  r0 holds resolved field
9083     *  r9 holds object
9084     */
9085.LOP_IPUT_VOLATILE_finish:
9086    @bl      common_squeak0
9087    mov     r1, rINST, lsr #8           @ r1<- A+
9088    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9089    and     r1, r1, #15                 @ r1<- A
9090    cmp     r9, #0                      @ check object for null
9091    GET_VREG(r0, r1)                    @ r0<- fp[A]
9092    beq     common_errNullObject        @ object was null
9093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9094    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9095    SMP_DMB                            @ releasing store
9096    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9097    GOTO_OPCODE(ip)                     @ jump to next instruction
9098
9099/* continuation for OP_SGET_VOLATILE */
9100
9101    /*
9102     * Continuation if the field has not yet been resolved.
9103     *  r1: BBBB field ref
9104     */
9105.LOP_SGET_VOLATILE_resolve:
9106    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9107    EXPORT_PC()                         @ resolve() could throw, so export now
9108    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9109    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9110    cmp     r0, #0                      @ success?
9111    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9112    b       common_exceptionThrown      @ no, handle exception
9113
9114/* continuation for OP_SPUT_VOLATILE */
9115
9116    /*
9117     * Continuation if the field has not yet been resolved.
9118     *  r1: BBBB field ref
9119     */
9120.LOP_SPUT_VOLATILE_resolve:
9121    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9122    EXPORT_PC()                         @ resolve() could throw, so export now
9123    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9124    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9125    cmp     r0, #0                      @ success?
9126    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9127    b       common_exceptionThrown      @ no, handle exception
9128
9129/* continuation for OP_IGET_OBJECT_VOLATILE */
9130
9131    /*
9132     * Currently:
9133     *  r0 holds resolved field
9134     *  r9 holds object
9135     */
9136.LOP_IGET_OBJECT_VOLATILE_finish:
9137    @bl      common_squeak0
9138    cmp     r9, #0                      @ check object for null
9139    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9140    beq     common_errNullObject        @ object was null
9141    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9142    SMP_DMB                            @ acquiring load
9143    mov     r2, rINST, lsr #8           @ r2<- A+
9144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9145    and     r2, r2, #15                 @ r2<- A
9146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9147    SET_VREG(r0, r2)                    @ fp[A]<- r0
9148    GOTO_OPCODE(ip)                     @ jump to next instruction
9149
9150/* continuation for OP_IGET_WIDE_VOLATILE */
9151
9152    /*
9153     * Currently:
9154     *  r0 holds resolved field
9155     *  r9 holds object
9156     */
9157.LOP_IGET_WIDE_VOLATILE_finish:
9158    cmp     r9, #0                      @ check object for null
9159    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9160    beq     common_errNullObject        @ object was null
9161    .if     1
9162    add     r0, r9, r3                  @ r0<- address of field
9163    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9164    .else
9165    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9166    .endif
9167    mov     r2, rINST, lsr #8           @ r2<- A+
9168    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9169    and     r2, r2, #15                 @ r2<- A
9170    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9172    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9173    GOTO_OPCODE(ip)                     @ jump to next instruction
9174
9175/* continuation for OP_IPUT_WIDE_VOLATILE */
9176
9177    /*
9178     * Currently:
9179     *  r0 holds resolved field
9180     *  r9 holds object
9181     */
9182.LOP_IPUT_WIDE_VOLATILE_finish:
9183    mov     r2, rINST, lsr #8           @ r2<- A+
9184    cmp     r9, #0                      @ check object for null
9185    and     r2, r2, #15                 @ r2<- A
9186    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9187    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9188    beq     common_errNullObject        @ object was null
9189    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9190    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9191    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9192    .if     1
9193    add     r2, r9, r3                  @ r2<- target address
9194    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9195    .else
9196    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9197    .endif
9198    GOTO_OPCODE(r10)                    @ jump to next instruction
9199
9200/* continuation for OP_SGET_WIDE_VOLATILE */
9201
9202    /*
9203     * Continuation if the field has not yet been resolved.
9204     *  r1: BBBB field ref
9205     *
9206     * Returns StaticField pointer in r0.
9207     */
9208.LOP_SGET_WIDE_VOLATILE_resolve:
9209    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9210    EXPORT_PC()                         @ resolve() could throw, so export now
9211    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9212    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9213    cmp     r0, #0                      @ success?
9214    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9215    b       common_exceptionThrown      @ no, handle exception
9216
9217/* continuation for OP_SPUT_WIDE_VOLATILE */
9218
9219    /*
9220     * Continuation if the field has not yet been resolved.
9221     *  r1: BBBB field ref
9222     *  r9: &fp[AA]
9223     *
9224     * Returns StaticField pointer in r2.
9225     */
9226.LOP_SPUT_WIDE_VOLATILE_resolve:
9227    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9228    EXPORT_PC()                         @ resolve() could throw, so export now
9229    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9230    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9231    cmp     r0, #0                      @ success?
9232    mov     r2, r0                      @ copy to r2
9233    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9234    b       common_exceptionThrown      @ no, handle exception
9235
9236/* continuation for OP_EXECUTE_INLINE */
9237
9238    /*
9239     * Extract args, call function.
9240     *  r0 = #of args (0-4)
9241     *  r10 = call index
9242     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9243     *
9244     * Other ideas:
9245     * - Use a jump table from the main piece to jump directly into the
9246     *   AND/LDR pairs.  Costs a data load, saves a branch.
9247     * - Have five separate pieces that do the loading, so we can work the
9248     *   interleave a little better.  Increases code size.
9249     */
9250.LOP_EXECUTE_INLINE_continue:
9251    rsb     r0, r0, #4                  @ r0<- 4-r0
9252    FETCH(r9, 2)                        @ r9<- FEDC
9253    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9254    bl      common_abort                @ (skipped due to ARM prefetch)
92554:  and     ip, r9, #0xf000             @ isolate F
9256    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92573:  and     ip, r9, #0x0f00             @ isolate E
9258    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92592:  and     ip, r9, #0x00f0             @ isolate D
9260    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92611:  and     ip, r9, #0x000f             @ isolate C
9262    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92630:
9264    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9265    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9266    @ (not reached)
9267
9268.LOP_EXECUTE_INLINE_table:
9269    .word   gDvmInlineOpsTable
9270
9271/* continuation for OP_EXECUTE_INLINE_RANGE */
9272
9273    /*
9274     * Extract args, call function.
9275     *  r0 = #of args (0-4)
9276     *  r10 = call index
9277     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9278     */
9279.LOP_EXECUTE_INLINE_RANGE_continue:
9280    rsb     r0, r0, #4                  @ r0<- 4-r0
9281    FETCH(r9, 2)                        @ r9<- CCCC
9282    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9283    bl      common_abort                @ (skipped due to ARM prefetch)
92844:  add     ip, r9, #3                  @ base+3
9285    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92863:  add     ip, r9, #2                  @ base+2
9287    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92882:  add     ip, r9, #1                  @ base+1
9289    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92901:  add     ip, r9, #0                  @ (nop)
9291    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92920:
9293    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9294    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9295    @ (not reached)
9296
9297.LOP_EXECUTE_INLINE_RANGE_table:
9298    .word   gDvmInlineOpsTable
9299
9300/* continuation for OP_IPUT_OBJECT_VOLATILE */
9301
9302    /*
9303     * Currently:
9304     *  r0 holds resolved field
9305     *  r9 holds object
9306     */
9307.LOP_IPUT_OBJECT_VOLATILE_finish:
9308    @bl      common_squeak0
9309    mov     r1, rINST, lsr #8           @ r1<- A+
9310    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9311    and     r1, r1, #15                 @ r1<- A
9312    cmp     r9, #0                      @ check object for null
9313    GET_VREG(r0, r1)                    @ r0<- fp[A]
9314    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9315    beq     common_errNullObject        @ object was null
9316    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9317    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9318    SMP_DMB                            @ releasing store
9319    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
9320    cmp     r0, #0                      @ stored a null reference?
9321    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9322    GOTO_OPCODE(ip)                     @ jump to next instruction
9323
9324/* continuation for OP_SGET_OBJECT_VOLATILE */
9325
9326    /*
9327     * Continuation if the field has not yet been resolved.
9328     *  r1: BBBB field ref
9329     */
9330.LOP_SGET_OBJECT_VOLATILE_resolve:
9331    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9332    EXPORT_PC()                         @ resolve() could throw, so export now
9333    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9334    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9335    cmp     r0, #0                      @ success?
9336    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9337    b       common_exceptionThrown      @ no, handle exception
9338
9339/* continuation for OP_SPUT_OBJECT_VOLATILE */
9340.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9341    mov     r2, rINST, lsr #8           @ r2<- AA
9342    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9343    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9344    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9345    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9347    SMP_DMB                            @ releasing store
9348    str     r1, [r0, #offStaticField_value]  @ field<- vAA
9349    cmp     r1, #0                      @ stored a null object?
9350    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9351    GOTO_OPCODE(ip)                     @ jump to next instruction
9352
9353    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9354    .global dvmAsmSisterEnd
9355dvmAsmSisterEnd:
9356
9357/* File: armv5te/footer.S */
9358
9359/*
9360 * ===========================================================================
9361 *  Common subroutines and data
9362 * ===========================================================================
9363 */
9364
9365
9366
9367    .text
9368    .align  2
9369
9370#if defined(WITH_JIT)
9371#if defined(WITH_SELF_VERIFICATION)
9372    .global dvmJitToInterpPunt
9373dvmJitToInterpPunt:
9374    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9375    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9376    mov    r3, #0
9377    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9378    b      jitSVShadowRunEnd            @ doesn't return
9379
9380    .global dvmJitToInterpSingleStep
9381dvmJitToInterpSingleStep:
9382    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9383    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9384    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9385    b      jitSVShadowRunEnd            @ doesn't return
9386
9387    .global dvmJitToInterpNoChainNoProfile
9388dvmJitToInterpNoChainNoProfile:
9389    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9390    mov    r0,rPC                       @ pass our target PC
9391    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9392    mov    r3, #0                       @ 0 means !inJitCodeCache
9393    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9394    b      jitSVShadowRunEnd            @ doesn't return
9395
9396    .global dvmJitToInterpTraceSelectNoChain
9397dvmJitToInterpTraceSelectNoChain:
9398    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9399    mov    r0,rPC                       @ pass our target PC
9400    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9401    mov    r3, #0                       @ 0 means !inJitCodeCache
9402    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9403    b      jitSVShadowRunEnd            @ doesn't return
9404
9405    .global dvmJitToInterpTraceSelect
9406dvmJitToInterpTraceSelect:
9407    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9408    ldr    r0,[lr, #-1]                 @ pass our target PC
9409    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9410    mov    r3, #0                       @ 0 means !inJitCodeCache
9411    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9412    b      jitSVShadowRunEnd            @ doesn't return
9413
9414    .global dvmJitToInterpBackwardBranch
9415dvmJitToInterpBackwardBranch:
9416    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9417    ldr    r0,[lr, #-1]                 @ pass our target PC
9418    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9419    mov    r3, #0                       @ 0 means !inJitCodeCache
9420    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9421    b      jitSVShadowRunEnd            @ doesn't return
9422
9423    .global dvmJitToInterpNormal
9424dvmJitToInterpNormal:
9425    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9426    ldr    r0,[lr, #-1]                 @ pass our target PC
9427    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9428    mov    r3, #0                       @ 0 means !inJitCodeCache
9429    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9430    b      jitSVShadowRunEnd            @ doesn't return
9431
9432    .global dvmJitToInterpNoChain
9433dvmJitToInterpNoChain:
9434    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9435    mov    r0,rPC                       @ pass our target PC
9436    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9437    mov    r3, #0                       @ 0 means !inJitCodeCache
9438    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9439    b      jitSVShadowRunEnd            @ doesn't return
9440#else
9441/*
9442 * Return from the translation cache to the interpreter when the compiler is
9443 * having issues translating/executing a Dalvik instruction. We have to skip
9444 * the code cache lookup otherwise it is possible to indefinitely bouce
9445 * between the interpreter and the code cache if the instruction that fails
9446 * to be compiled happens to be at a trace start.
9447 */
9448    .global dvmJitToInterpPunt
9449dvmJitToInterpPunt:
9450    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9451    mov    rPC, r0
9452#if defined(WITH_JIT_TUNING)
9453    mov    r0,lr
9454    bl     dvmBumpPunt;
9455#endif
9456    EXPORT_PC()
9457    mov    r0, #0
9458    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9459    adrl   rIBASE, dvmAsmInstructionStart
9460    FETCH_INST()
9461    GET_INST_OPCODE(ip)
9462    GOTO_OPCODE(ip)
9463
9464/*
9465 * Return to the interpreter to handle a single instruction.
9466 * On entry:
9467 *    r0 <= PC
9468 *    r1 <= PC of resume instruction
9469 *    lr <= resume point in translation
9470 */
9471    .global dvmJitToInterpSingleStep
9472dvmJitToInterpSingleStep:
9473    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9474    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9475    mov    r1,#kInterpEntryInstr
9476    @ enum is 4 byte in aapcs-EABI
9477    str    r1, [rGLUE, #offGlue_entryPoint]
9478    mov    rPC,r0
9479    EXPORT_PC()
9480
9481    adrl   rIBASE, dvmAsmInstructionStart
9482    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9483    str    r2,[rGLUE,#offGlue_jitState]
9484    mov    r1,#1                  @ set changeInterp to bail to debug interp
9485    b      common_gotoBail
9486
9487/*
9488 * Return from the translation cache and immediately request
9489 * a translation for the exit target.  Commonly used for callees.
9490 */
9491    .global dvmJitToInterpTraceSelectNoChain
9492dvmJitToInterpTraceSelectNoChain:
9493#if defined(WITH_JIT_TUNING)
9494    bl     dvmBumpNoChain
9495#endif
9496    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9497    mov    r0,rPC
9498    bl     dvmJitGetCodeAddr        @ Is there a translation?
9499    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9500    mov    r1, rPC                  @ arg1 of translation may need this
9501    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9502    cmp    r0,#0                    @ !0 means translation exists
9503    bxne   r0                       @ continue native execution if so
9504    b      2f                       @ branch over to use the interpreter
9505
9506/*
9507 * Return from the translation cache and immediately request
9508 * a translation for the exit target.  Commonly used following
9509 * invokes.
9510 */
9511    .global dvmJitToInterpTraceSelect
9512dvmJitToInterpTraceSelect:
9513    ldr    rPC,[lr, #-1]           @ get our target PC
9514    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9515    add    rINST,lr,#-5            @ save start of chain branch
9516    add    rINST, #-4              @  .. which is 9 bytes back
9517    mov    r0,rPC
9518    bl     dvmJitGetCodeAddr       @ Is there a translation?
9519    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9520    cmp    r0,#0
9521    beq    2f
9522    mov    r1,rINST
9523    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9524    mov    r1, rPC                  @ arg1 of translation may need this
9525    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9526    cmp    r0,#0                    @ successful chain?
9527    bxne   r0                       @ continue native execution
9528    b      toInterpreter            @ didn't chain - resume with interpreter
9529
9530/* No translation, so request one if profiling isn't disabled*/
95312:
9532    adrl   rIBASE, dvmAsmInstructionStart
9533    GET_JIT_PROF_TABLE(r0)
9534    FETCH_INST()
9535    cmp    r0, #0
9536    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9537    bne    common_selectTrace
9538    GET_INST_OPCODE(ip)
9539    GOTO_OPCODE(ip)
9540
9541/*
9542 * Return from the translation cache to the interpreter.
9543 * The return was done with a BLX from thumb mode, and
9544 * the following 32-bit word contains the target rPC value.
9545 * Note that lr (r14) will have its low-order bit set to denote
9546 * its thumb-mode origin.
9547 *
9548 * We'll need to stash our lr origin away, recover the new
9549 * target and then check to see if there is a translation available
9550 * for our new target.  If so, we do a translation chain and
9551 * go back to native execution.  Otherwise, it's back to the
9552 * interpreter (after treating this entry as a potential
9553 * trace start).
9554 */
9555    .global dvmJitToInterpNormal
9556dvmJitToInterpNormal:
9557    ldr    rPC,[lr, #-1]           @ get our target PC
9558    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9559    add    rINST,lr,#-5            @ save start of chain branch
9560    add    rINST,#-4               @ .. which is 9 bytes back
9561#if defined(WITH_JIT_TUNING)
9562    bl     dvmBumpNormal
9563#endif
9564    mov    r0,rPC
9565    bl     dvmJitGetCodeAddr        @ Is there a translation?
9566    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9567    cmp    r0,#0
9568    beq    toInterpreter            @ go if not, otherwise do chain
9569    mov    r1,rINST
9570    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9571    mov    r1, rPC                  @ arg1 of translation may need this
9572    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9573    cmp    r0,#0                    @ successful chain?
9574    bxne   r0                       @ continue native execution
9575    b      toInterpreter            @ didn't chain - resume with interpreter
9576
9577/*
9578 * Return from the translation cache to the interpreter to do method invocation.
9579 * Check if translation exists for the callee, but don't chain to it.
9580 */
9581    .global dvmJitToInterpNoChainNoProfile
9582dvmJitToInterpNoChainNoProfile:
9583#if defined(WITH_JIT_TUNING)
9584    bl     dvmBumpNoChain
9585#endif
9586    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9587    mov    r0,rPC
9588    bl     dvmJitGetCodeAddr        @ Is there a translation?
9589    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9590    mov    r1, rPC                  @ arg1 of translation may need this
9591    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9592    cmp    r0,#0
9593    bxne   r0                       @ continue native execution if so
9594    EXPORT_PC()
9595    adrl   rIBASE, dvmAsmInstructionStart
9596    FETCH_INST()
9597    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9598    GOTO_OPCODE(ip)                     @ jump to next instruction
9599
9600/*
9601 * Return from the translation cache to the interpreter to do method invocation.
9602 * Check if translation exists for the callee, but don't chain to it.
9603 */
9604    .global dvmJitToInterpNoChain
9605dvmJitToInterpNoChain:
9606#if defined(WITH_JIT_TUNING)
9607    bl     dvmBumpNoChain
9608#endif
9609    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9610    mov    r0,rPC
9611    bl     dvmJitGetCodeAddr        @ Is there a translation?
9612    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9613    mov    r1, rPC                  @ arg1 of translation may need this
9614    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9615    cmp    r0,#0
9616    bxne   r0                       @ continue native execution if so
9617#endif
9618
9619/*
9620 * No translation, restore interpreter regs and start interpreting.
9621 * rGLUE & rFP were preserved in the translated code, and rPC has
9622 * already been restored by the time we get here.  We'll need to set
9623 * up rIBASE & rINST, and load the address of the JitTable into r0.
9624 */
9625toInterpreter:
9626    EXPORT_PC()
9627    adrl   rIBASE, dvmAsmInstructionStart
9628    FETCH_INST()
9629    GET_JIT_PROF_TABLE(r0)
9630    @ NOTE: intended fallthrough
9631
9632/*
9633 * Common code to update potential trace start counter, and initiate
9634 * a trace-build if appropriate.  On entry, rPC should point to the
9635 * next instruction to execute, and rINST should be already loaded with
9636 * the next opcode word, and r0 holds a pointer to the jit profile
9637 * table (pJitProfTable).
9638 */
9639common_testUpdateProfile:
9640    cmp     r0,#0
9641    GET_INST_OPCODE(ip)
9642    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9643
9644common_updateProfile:
9645    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9646    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9647    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9648    GET_INST_OPCODE(ip)
9649    subs    r1,r1,#1           @ decrement counter
9650    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9651    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9652
9653/*
9654 * Here, we switch to the debug interpreter to request
9655 * trace selection.  First, though, check to see if there
9656 * is already a native translation in place (and, if so,
9657 * jump to it now).
9658 */
9659    GET_JIT_THRESHOLD(r1)
9660    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9661    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9662    EXPORT_PC()
9663    mov     r0,rPC
9664    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9665    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9666    mov     r1, rPC                     @ arg1 of translation may need this
9667    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9668    cmp     r0,#0
9669#if !defined(WITH_SELF_VERIFICATION)
9670    bxne    r0                          @ jump to the translation
9671    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9672    @ fall-through to common_selectTrace
9673#else
9674    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9675    beq     common_selectTrace
9676    /*
9677     * At this point, we have a target translation.  However, if
9678     * that translation is actually the interpret-only pseudo-translation
9679     * we want to treat it the same as no translation.
9680     */
9681    mov     r10, r0                     @ save target
9682    bl      dvmCompilerGetInterpretTemplate
9683    cmp     r0, r10                     @ special case?
9684    bne     jitSVShadowRunStart         @ set up self verification shadow space
9685    @ Need to clear the inJitCodeCache flag
9686    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
9687    mov    r3, #0                       @ 0 means not in the JIT code cache
9688    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9689    GET_INST_OPCODE(ip)
9690    GOTO_OPCODE(ip)
9691    /* no return */
9692#endif
9693
9694/*
9695 * On entry:
9696 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9697 */
9698common_selectTrace:
9699    str     r2,[rGLUE,#offGlue_jitState]
9700    mov     r2,#kInterpEntryInstr       @ normal entry reason
9701    str     r2,[rGLUE,#offGlue_entryPoint]
9702    mov     r1,#1                       @ set changeInterp
9703    b       common_gotoBail
9704
9705#if defined(WITH_SELF_VERIFICATION)
9706/*
9707 * Save PC and registers to shadow memory for self verification mode
9708 * before jumping to native translation.
9709 * On entry:
9710 *    rPC, rFP, rGLUE: the values that they should contain
9711 *    r10: the address of the target translation.
9712 */
9713jitSVShadowRunStart:
9714    mov     r0,rPC                      @ r0<- program counter
9715    mov     r1,rFP                      @ r1<- frame pointer
9716    mov     r2,rGLUE                    @ r2<- InterpState pointer
9717    mov     r3,r10                      @ r3<- target translation
9718    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9719    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9720    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9721    bx      r10                         @ jump to the translation
9722
9723/*
9724 * Restore PC, registers, and interpState to original values
9725 * before jumping back to the interpreter.
9726 */
9727jitSVShadowRunEnd:
9728    mov    r1,rFP                        @ pass ending fp
9729    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9730    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9731    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9732    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9733    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9734    cmp    r1,#0                         @ check for punt condition
9735    beq    1f
9736    mov    r2,#kJitSelfVerification      @ ask for self verification
9737    str    r2,[rGLUE,#offGlue_jitState]
9738    mov    r2,#kInterpEntryInstr         @ normal entry reason
9739    str    r2,[rGLUE,#offGlue_entryPoint]
9740    mov    r1,#1                         @ set changeInterp
9741    b      common_gotoBail
9742
97431:                                       @ exit to interpreter without check
9744    EXPORT_PC()
9745    adrl   rIBASE, dvmAsmInstructionStart
9746    FETCH_INST()
9747    GET_INST_OPCODE(ip)
9748    GOTO_OPCODE(ip)
9749#endif
9750
9751#endif
9752
9753/*
9754 * Common code when a backward branch is taken.
9755 *
9756 * TODO: we could avoid a branch by just setting r0 and falling through
9757 * into the common_periodicChecks code, and having a test on r0 at the
9758 * end determine if we should return to the caller or update & branch to
9759 * the next instr.
9760 *
9761 * On entry:
9762 *  r9 is PC adjustment *in bytes*
9763 */
9764common_backwardBranch:
9765    mov     r0, #kInterpEntryInstr
9766    bl      common_periodicChecks
9767#if defined(WITH_JIT)
9768    GET_JIT_PROF_TABLE(r0)
9769    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9770    cmp     r0,#0
9771    bne     common_updateProfile
9772    GET_INST_OPCODE(ip)
9773    GOTO_OPCODE(ip)
9774#else
9775    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9777    GOTO_OPCODE(ip)                     @ jump to next instruction
9778#endif
9779
9780
9781/*
9782 * Need to see if the thread needs to be suspended or debugger/profiler
9783 * activity has begun.  If so, we suspend the thread or side-exit to
9784 * the debug interpreter as appropriate.
9785 *
9786 * The common case is no activity on any of these, so we want to figure
9787 * that out quickly.  If something is up, we can then sort out what.
9788 *
9789 * We want to be fast if the VM was built without debugger or profiler
9790 * support, but we also need to recognize that the system is usually
9791 * shipped with both of these enabled.
9792 *
9793 * TODO: reduce this so we're just checking a single location.
9794 *
9795 * On entry:
9796 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9797 *  r9 is trampoline PC adjustment *in bytes*
9798 */
9799common_periodicChecks:
9800    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9801
9802    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9803    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9804
9805    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9806
9807    cmp     r1, #0                      @ debugger enabled?
9808    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9809    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9810    orrnes  ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9811    /*
9812     * Don't switch the interpreter in the libdvm_traceview build even if the
9813     * profiler is active.
9814     * The code here is opted for less intrusion instead of performance.
9815     * That is, *pActiveProfilers is still loaded into r2 even though it is not
9816     * used when WITH_INLINE_PROFILING is defined.
9817     */
9818#if !defined(WITH_INLINE_PROFILING)
9819    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9820#endif
9821
9822
9823    bxeq    lr                          @ all zero, return
9824
9825    /*
9826     * One or more interesting events have happened.  Figure out what.
9827     *
9828     * If debugging or profiling are compiled in, we need to disambiguate.
9829     *
9830     * r0 still holds the reentry type.
9831     */
9832    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9833    cmp     ip, #0                      @ want suspend?
9834    beq     1f                          @ no, must be debugger/profiler
9835
9836    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9837#if defined(WITH_JIT)
9838    /*
9839     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9840     * doubles as the Jit's on/off switch.
9841     */
9842    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9843    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9844    ldr     r3, [r3] @ r3 <- pJitProfTable
9845    EXPORT_PC()                         @ need for precise GC
9846    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9847#else
9848    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9849    EXPORT_PC()                         @ need for precise GC
9850#endif
9851    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9852    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9853
9854    /*
9855     * Reload the debugger/profiler enable flags.  We're checking to see
9856     * if either of these got set while we were suspended.
9857     *
9858     * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9859     * is enabled or not as the profiling will be done inline.
9860     */
9861    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9862    cmp     r1, #0                      @ debugger enabled?
9863    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9864
9865#if !defined(WITH_INLINE_PROFILING)
9866    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9867    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9868    orrs    r1, r1, r2
9869#else
9870    cmp     r1, #0                      @ only consult the debuggerActive flag
9871#endif
9872
9873    beq     2f
9874
98751:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9876    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9877    add     rPC, rPC, r9                @ update rPC
9878    mov     r1, #1                      @ "want switch" = true
9879    b       common_gotoBail             @ side exit
9880
98812:
9882    bx      lr                          @ nothing to do, return
9883
9884
9885/*
9886 * The equivalent of "goto bail", this calls through the "bail handler".
9887 *
9888 * State registers will be saved to the "glue" area before bailing.
9889 *
9890 * On entry:
9891 *  r1 is "bool changeInterp", indicating if we want to switch to the
9892 *     other interpreter or just bail all the way out
9893 */
9894common_gotoBail:
9895    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9896    mov     r0, rGLUE                   @ r0<- glue ptr
9897    b       dvmMterpStdBail             @ call(glue, changeInterp)
9898
9899    @add     r1, r1, #1                  @ using (boolean+1)
9900    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9901    @bl      _longjmp                    @ does not return
9902    @bl      common_abort
9903
9904
9905/*
9906 * Common code for method invocation with range.
9907 *
9908 * On entry:
9909 *  r0 is "Method* methodToCall", the method we're trying to call
9910 */
9911common_invokeMethodRange:
9912.LinvokeNewRange:
9913    @ prepare to copy args to "outs" area of current frame
9914    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9915    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9916    beq     .LinvokeArgsDone            @ if no args, skip the rest
9917    FETCH(r1, 2)                        @ r1<- CCCC
9918
9919    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9920    @ (very few methods have > 10 args; could unroll for common cases)
9921    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9922    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9923    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
99241:  ldr     r1, [r3], #4                @ val = *fp++
9925    subs    r2, r2, #1                  @ count--
9926    str     r1, [r10], #4               @ *outs++ = val
9927    bne     1b                          @ ...while count != 0
9928    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9929    b       .LinvokeArgsDone
9930
9931/*
9932 * Common code for method invocation without range.
9933 *
9934 * On entry:
9935 *  r0 is "Method* methodToCall", the method we're trying to call
9936 */
9937common_invokeMethodNoRange:
9938.LinvokeNewNoRange:
9939    @ prepare to copy args to "outs" area of current frame
9940    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9941    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9942    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9943    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9944    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9945    beq     .LinvokeArgsDone
9946
9947    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9948.LinvokeNonRange:
9949    rsb     r2, r2, #5                  @ r2<- 5-r2
9950    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9951    bl      common_abort                @ (skipped due to ARM prefetch)
99525:  and     ip, rINST, #0x0f00          @ isolate A
9953    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9954    mov     r0, r0                      @ nop
9955    str     r2, [r10, #-4]!             @ *--outs = vA
99564:  and     ip, r1, #0xf000             @ isolate G
9957    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9958    mov     r0, r0                      @ nop
9959    str     r2, [r10, #-4]!             @ *--outs = vG
99603:  and     ip, r1, #0x0f00             @ isolate F
9961    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9962    mov     r0, r0                      @ nop
9963    str     r2, [r10, #-4]!             @ *--outs = vF
99642:  and     ip, r1, #0x00f0             @ isolate E
9965    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9966    mov     r0, r0                      @ nop
9967    str     r2, [r10, #-4]!             @ *--outs = vE
99681:  and     ip, r1, #0x000f             @ isolate D
9969    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9970    mov     r0, r0                      @ nop
9971    str     r2, [r10, #-4]!             @ *--outs = vD
99720:  @ fall through to .LinvokeArgsDone
9973
9974.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9975    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9976    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9977    @ find space for the new stack frame, check for overflow
9978    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9979    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9980    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9981@    bl      common_dumpRegs
9982    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9983    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9984    cmp     r3, r9                      @ bottom < interpStackEnd?
9985    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9986    blo     .LstackOverflow             @ yes, this frame will overflow stack
9987
9988    @ set up newSaveArea
9989#ifdef EASY_GDB
9990    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9991    str     ip, [r10, #offStackSaveArea_prevSave]
9992#endif
9993    str     rFP, [r10, #offStackSaveArea_prevFrame]
9994    str     rPC, [r10, #offStackSaveArea_savedPc]
9995#if defined(WITH_JIT)
9996    mov     r9, #0
9997    str     r9, [r10, #offStackSaveArea_returnAddr]
9998#endif
9999#if defined(WITH_INLINE_PROFILING)
10000    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10001    mov     r1, r6
10002    @ r0=methodToCall, r1=rGlue
10003    bl      dvmFastMethodTraceEnter
10004    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10005#endif
10006    str     r0, [r10, #offStackSaveArea_method]
10007    tst     r3, #ACC_NATIVE
10008    bne     .LinvokeNative
10009
10010    /*
10011    stmfd   sp!, {r0-r3}
10012    bl      common_printNewline
10013    mov     r0, rFP
10014    mov     r1, #0
10015    bl      dvmDumpFp
10016    ldmfd   sp!, {r0-r3}
10017    stmfd   sp!, {r0-r3}
10018    mov     r0, r1
10019    mov     r1, r10
10020    bl      dvmDumpFp
10021    bl      common_printNewline
10022    ldmfd   sp!, {r0-r3}
10023    */
10024
10025    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10026    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10027    mov     rPC, r2                         @ publish new rPC
10028    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10029
10030    @ Update "glue" values for the new method
10031    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10032    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10033    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10034#if defined(WITH_JIT)
10035    GET_JIT_PROF_TABLE(r0)
10036    mov     rFP, r1                         @ fp = newFp
10037    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10038    mov     rINST, r9                       @ publish new rINST
10039    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10040    cmp     r0,#0
10041    bne     common_updateProfile
10042    GOTO_OPCODE(ip)                         @ jump to next instruction
10043#else
10044    mov     rFP, r1                         @ fp = newFp
10045    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10046    mov     rINST, r9                       @ publish new rINST
10047    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10048    GOTO_OPCODE(ip)                         @ jump to next instruction
10049#endif
10050
10051.LinvokeNative:
10052    @ Prep for the native call
10053    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10054    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10055    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10056    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10057    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10058    mov     r9, r3                      @ r9<- glue->self (preserve)
10059
10060    mov     r2, r0                      @ r2<- methodToCall
10061    mov     r0, r1                      @ r0<- newFp (points to args)
10062    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10063
10064#ifdef ASSIST_DEBUGGER
10065    /* insert fake function header to help gdb find the stack frame */
10066    b       .Lskip
10067    .type   dalvik_mterp, %function
10068dalvik_mterp:
10069    .fnstart
10070    MTERP_ENTRY1
10071    MTERP_ENTRY2
10072.Lskip:
10073#endif
10074
10075#if defined(WITH_INLINE_PROFILING)
10076    @ r2=JNIMethod, r6=rGLUE
10077    stmfd   sp!, {r2,r6}
10078#endif
10079
10080    mov     lr, pc                      @ set return addr
10081    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10082
10083#if defined(WITH_INLINE_PROFILING)
10084    @ r0=JNIMethod, r1=rGLUE
10085    ldmfd   sp!, {r0-r1}
10086    bl      dvmFastNativeMethodTraceExit
10087#endif
10088
10089#if defined(WITH_JIT)
10090    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10091#endif
10092
10093    @ native return; r9=self, r10=newSaveArea
10094    @ equivalent to dvmPopJniLocals
10095    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10096    ldr     r1, [r9, #offThread_exception] @ check for exception
10097#if defined(WITH_JIT)
10098    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10099#endif
10100    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10101    cmp     r1, #0                      @ null?
10102    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10103#if defined(WITH_JIT)
10104    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10105#endif
10106    bne     common_exceptionThrown      @ no, handle exception
10107
10108    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10109    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10110    GOTO_OPCODE(ip)                     @ jump to next instruction
10111
10112.LstackOverflow:    @ r0=methodToCall
10113    mov     r1, r0                      @ r1<- methodToCall
10114    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10115    bl      dvmHandleStackOverflow
10116    b       common_exceptionThrown
10117#ifdef ASSIST_DEBUGGER
10118    .fnend
10119#endif
10120
10121
10122    /*
10123     * Common code for method invocation, calling through "glue code".
10124     *
10125     * TODO: now that we have range and non-range invoke handlers, this
10126     *       needs to be split into two.  Maybe just create entry points
10127     *       that set r9 and jump here?
10128     *
10129     * On entry:
10130     *  r0 is "Method* methodToCall", the method we're trying to call
10131     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10132     */
10133     .if    0
10134.LinvokeOld:
10135    sub     sp, sp, #8                  @ space for args + pad
10136    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10137    mov     r2, r0                      @ A2<- methodToCall
10138    mov     r0, rGLUE                   @ A0<- glue
10139    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10140    mov     r1, r9                      @ A1<- methodCallRange
10141    mov     r3, rINST, lsr #8           @ A3<- AA
10142    str     ip, [sp, #0]                @ A4<- ip
10143    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10144    add     sp, sp, #8                  @ remove arg area
10145    b       common_resumeAfterGlueCall  @ continue to next instruction
10146    .endif
10147
10148
10149
10150/*
10151 * Common code for handling a return instruction.
10152 *
10153 * This does not return.
10154 */
10155common_returnFromMethod:
10156.LreturnNew:
10157    mov     r0, #kInterpEntryReturn
10158    mov     r9, #0
10159    bl      common_periodicChecks
10160
10161#if defined(WITH_INLINE_PROFILING)
10162    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10163    mov     r0, r6
10164    @ r0=rGlue
10165    bl      dvmFastJavaMethodTraceExit
10166    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10167#endif
10168    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10169    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10170    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10171    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10172                                        @ r2<- method we're returning to
10173    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10174    cmp     r2, #0                      @ is this a break frame?
10175    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10176    mov     r1, #0                      @ "want switch" = false
10177    beq     common_gotoBail             @ break frame, bail out completely
10178
10179    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10180    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10181    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10182    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10183#if defined(WITH_JIT)
10184    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10185    mov     rPC, r9                     @ publish new rPC
10186    str     r1, [rGLUE, #offGlue_methodClassDex]
10187    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10188    cmp     r10, #0                      @ caller is compiled code
10189    blxne   r10
10190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10191    GOTO_OPCODE(ip)                     @ jump to next instruction
10192#else
10193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10194    mov     rPC, r9                     @ publish new rPC
10195    str     r1, [rGLUE, #offGlue_methodClassDex]
10196    GOTO_OPCODE(ip)                     @ jump to next instruction
10197#endif
10198
10199    /*
10200     * Return handling, calls through "glue code".
10201     */
10202     .if    0
10203.LreturnOld:
10204    SAVE_PC_FP_TO_GLUE()                @ export state
10205    mov     r0, rGLUE                   @ arg to function
10206    bl      dvmMterp_returnFromMethod
10207    b       common_resumeAfterGlueCall
10208    .endif
10209
10210
10211/*
10212 * Somebody has thrown an exception.  Handle it.
10213 *
10214 * If the exception processing code returns to us (instead of falling
10215 * out of the interpreter), continue with whatever the next instruction
10216 * now happens to be.
10217 *
10218 * This does not return.
10219 */
10220     .global dvmMterpCommonExceptionThrown
10221dvmMterpCommonExceptionThrown:
10222common_exceptionThrown:
10223.LexceptionNew:
10224    mov     r0, #kInterpEntryThrow
10225    mov     r9, #0
10226    bl      common_periodicChecks
10227
10228    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10229    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10230    mov     r1, r10                     @ r1<- self
10231    mov     r0, r9                      @ r0<- exception
10232    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10233    mov     r3, #0                      @ r3<- NULL
10234    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10235
10236    /* set up args and a local for "&fp" */
10237    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10238    str     rFP, [sp, #-4]!             @ *--sp = fp
10239    mov     ip, sp                      @ ip<- &fp
10240    mov     r3, #0                      @ r3<- false
10241    str     ip, [sp, #-4]!              @ *--sp = &fp
10242    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10243    mov     r0, r10                     @ r0<- self
10244    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10245    mov     r2, r9                      @ r2<- exception
10246    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10247    mov     r1, r1, asr #1              @ r1<- offset in code units
10248
10249    /* call, r0 gets catchRelPc (a code-unit offset) */
10250    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10251
10252    /* fix earlier stack overflow if necessary; may trash rFP */
10253    ldrb    r1, [r10, #offThread_stackOverflowed]
10254    cmp     r1, #0                      @ did we overflow earlier?
10255    beq     1f                          @ no, skip ahead
10256    mov     rFP, r0                     @ save relPc result in rFP
10257    mov     r0, r10                     @ r0<- self
10258    mov     r1, r9                      @ r1<- exception
10259    bl      dvmCleanupStackOverflow     @ call(self)
10260    mov     r0, rFP                     @ restore result
102611:
10262
10263    /* update frame pointer and check result from dvmFindCatchBlock */
10264    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10265    cmp     r0, #0                      @ is catchRelPc < 0?
10266    add     sp, sp, #8                  @ restore stack
10267    bmi     .LnotCaughtLocally
10268
10269    /* adjust locals to match self->curFrame and updated PC */
10270    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10271    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10272    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10273    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10274    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10275    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10276    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10277    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10278
10279    /* release the tracked alloc on the exception */
10280    mov     r0, r9                      @ r0<- exception
10281    mov     r1, r10                     @ r1<- self
10282    bl      dvmReleaseTrackedAlloc      @ release the exception
10283
10284    /* restore the exception if the handler wants it */
10285    FETCH_INST()                        @ load rINST from rPC
10286    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10287    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10288    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10289    GOTO_OPCODE(ip)                     @ jump to next instruction
10290
10291.LnotCaughtLocally: @ r9=exception, r10=self
10292    /* fix stack overflow if necessary */
10293    ldrb    r1, [r10, #offThread_stackOverflowed]
10294    cmp     r1, #0                      @ did we overflow earlier?
10295    movne   r0, r10                     @ if yes: r0<- self
10296    movne   r1, r9                      @ if yes: r1<- exception
10297    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10298
10299    @ may want to show "not caught locally" debug messages here
10300#if DVM_SHOW_EXCEPTION >= 2
10301    /* call __android_log_print(prio, tag, format, ...) */
10302    /* "Exception %s from %s:%d not caught locally" */
10303    @ dvmLineNumFromPC(method, pc - method->insns)
10304    ldr     r0, [rGLUE, #offGlue_method]
10305    ldr     r1, [r0, #offMethod_insns]
10306    sub     r1, rPC, r1
10307    asr     r1, r1, #1
10308    bl      dvmLineNumFromPC
10309    str     r0, [sp, #-4]!
10310    @ dvmGetMethodSourceFile(method)
10311    ldr     r0, [rGLUE, #offGlue_method]
10312    bl      dvmGetMethodSourceFile
10313    str     r0, [sp, #-4]!
10314    @ exception->clazz->descriptor
10315    ldr     r3, [r9, #offObject_clazz]
10316    ldr     r3, [r3, #offClassObject_descriptor]
10317    @
10318    ldr     r2, strExceptionNotCaughtLocally
10319    ldr     r1, strLogTag
10320    mov     r0, #3                      @ LOG_DEBUG
10321    bl      __android_log_print
10322#endif
10323    str     r9, [r10, #offThread_exception] @ restore exception
10324    mov     r0, r9                      @ r0<- exception
10325    mov     r1, r10                     @ r1<- self
10326    bl      dvmReleaseTrackedAlloc      @ release the exception
10327    mov     r1, #0                      @ "want switch" = false
10328    b       common_gotoBail             @ bail out
10329
10330
10331    /*
10332     * Exception handling, calls through "glue code".
10333     */
10334    .if     0
10335.LexceptionOld:
10336    SAVE_PC_FP_TO_GLUE()                @ export state
10337    mov     r0, rGLUE                   @ arg to function
10338    bl      dvmMterp_exceptionThrown
10339    b       common_resumeAfterGlueCall
10340    .endif
10341
10342
10343/*
10344 * After returning from a "glued" function, pull out the updated
10345 * values and start executing at the next instruction.
10346 */
10347common_resumeAfterGlueCall:
10348    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10349    FETCH_INST()                        @ load rINST from rPC
10350    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10351    GOTO_OPCODE(ip)                     @ jump to next instruction
10352
10353/*
10354 * Invalid array index. Note that our calling convention is strange; we use r1
10355 * and r3 because those just happen to be the registers all our callers are
10356 * using. We shuffle them here before calling the C function.
10357 * r1: index
10358 * r3: size
10359 */
10360common_errArrayIndex:
10361    EXPORT_PC()
10362    mov     r0, r1
10363    mov     r1, r3
10364    bl      dvmThrowAIOOBE
10365    b       common_exceptionThrown
10366
10367/*
10368 * Invalid array value.
10369 */
10370common_errArrayStore:
10371    EXPORT_PC()
10372    ldr     r0, strArrayStoreException
10373    mov     r1, #0
10374    bl      dvmThrowException
10375    b       common_exceptionThrown
10376
10377/*
10378 * Integer divide or mod by zero.
10379 */
10380common_errDivideByZero:
10381    EXPORT_PC()
10382    ldr     r0, strArithmeticException
10383    ldr     r1, strDivideByZero
10384    bl      dvmThrowException
10385    b       common_exceptionThrown
10386
10387/*
10388 * Attempt to allocate an array with a negative size.
10389 */
10390common_errNegativeArraySize:
10391    EXPORT_PC()
10392    ldr     r0, strNegativeArraySizeException
10393    mov     r1, #0
10394    bl      dvmThrowException
10395    b       common_exceptionThrown
10396
10397/*
10398 * Invocation of a non-existent method.
10399 */
10400common_errNoSuchMethod:
10401    EXPORT_PC()
10402    ldr     r0, strNoSuchMethodError
10403    mov     r1, #0
10404    bl      dvmThrowException
10405    b       common_exceptionThrown
10406
10407/*
10408 * We encountered a null object when we weren't expecting one.  We
10409 * export the PC, throw a NullPointerException, and goto the exception
10410 * processing code.
10411 */
10412common_errNullObject:
10413    EXPORT_PC()
10414    ldr     r0, strNullPointerException
10415    mov     r1, #0
10416    bl      dvmThrowException
10417    b       common_exceptionThrown
10418
10419/*
10420 * For debugging, cause an immediate fault.  The source address will
10421 * be in lr (use a bl instruction to jump here).
10422 */
10423common_abort:
10424    ldr     pc, .LdeadFood
10425.LdeadFood:
10426    .word   0xdeadf00d
10427
10428/*
10429 * Spit out a "we were here", preserving all registers.  (The attempt
10430 * to save ip won't work, but we need to save an even number of
10431 * registers for EABI 64-bit stack alignment.)
10432 */
10433    .macro  SQUEAK num
10434common_squeak\num:
10435    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10436    ldr     r0, strSqueak
10437    mov     r1, #\num
10438    bl      printf
10439    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10440    bx      lr
10441    .endm
10442
10443    SQUEAK  0
10444    SQUEAK  1
10445    SQUEAK  2
10446    SQUEAK  3
10447    SQUEAK  4
10448    SQUEAK  5
10449
10450/*
10451 * Spit out the number in r0, preserving registers.
10452 */
10453common_printNum:
10454    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10455    mov     r1, r0
10456    ldr     r0, strSqueak
10457    bl      printf
10458    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10459    bx      lr
10460
10461/*
10462 * Print a newline, preserving registers.
10463 */
10464common_printNewline:
10465    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10466    ldr     r0, strNewline
10467    bl      printf
10468    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10469    bx      lr
10470
10471    /*
10472     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10473     */
10474common_printHex:
10475    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10476    mov     r1, r0
10477    ldr     r0, strPrintHex
10478    bl      printf
10479    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10480    bx      lr
10481
10482/*
10483 * Print the 64-bit quantity in r0-r1, preserving registers.
10484 */
10485common_printLong:
10486    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10487    mov     r3, r1
10488    mov     r2, r0
10489    ldr     r0, strPrintLong
10490    bl      printf
10491    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10492    bx      lr
10493
10494/*
10495 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10496 */
10497common_printMethod:
10498    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10499    bl      dvmMterpPrintMethod
10500    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10501    bx      lr
10502
10503/*
10504 * Call a C helper function that dumps regs and possibly some
10505 * additional info.  Requires the C function to be compiled in.
10506 */
10507    .if     0
10508common_dumpRegs:
10509    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10510    bl      dvmMterpDumpArmRegs
10511    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10512    bx      lr
10513    .endif
10514
10515#if 0
10516/*
10517 * Experiment on VFP mode.
10518 *
10519 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10520 *
10521 * Updates the bits specified by "mask", setting them to the values in "val".
10522 */
10523setFPSCR:
10524    and     r0, r0, r1                  @ make sure no stray bits are set
10525    fmrx    r2, fpscr                   @ get VFP reg
10526    mvn     r1, r1                      @ bit-invert mask
10527    and     r2, r2, r1                  @ clear masked bits
10528    orr     r2, r2, r0                  @ set specified bits
10529    fmxr    fpscr, r2                   @ set VFP reg
10530    mov     r0, r2                      @ return new value
10531    bx      lr
10532
10533    .align  2
10534    .global dvmConfigureFP
10535    .type   dvmConfigureFP, %function
10536dvmConfigureFP:
10537    stmfd   sp!, {ip, lr}
10538    /* 0x03000000 sets DN/FZ */
10539    /* 0x00009f00 clears the six exception enable flags */
10540    bl      common_squeak0
10541    mov     r0, #0x03000000             @ r0<- 0x03000000
10542    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10543    bl      setFPSCR
10544    ldmfd   sp!, {ip, pc}
10545#endif
10546
10547
10548/*
10549 * String references, must be close to the code that uses them.
10550 */
10551    .align  2
10552strArithmeticException:
10553    .word   .LstrArithmeticException
10554strArrayStoreException:
10555    .word   .LstrArrayStoreException
10556strDivideByZero:
10557    .word   .LstrDivideByZero
10558strNegativeArraySizeException:
10559    .word   .LstrNegativeArraySizeException
10560strNoSuchMethodError:
10561    .word   .LstrNoSuchMethodError
10562strNullPointerException:
10563    .word   .LstrNullPointerException
10564
10565strLogTag:
10566    .word   .LstrLogTag
10567strExceptionNotCaughtLocally:
10568    .word   .LstrExceptionNotCaughtLocally
10569
10570strNewline:
10571    .word   .LstrNewline
10572strSqueak:
10573    .word   .LstrSqueak
10574strPrintHex:
10575    .word   .LstrPrintHex
10576strPrintLong:
10577    .word   .LstrPrintLong
10578
10579/*
10580 * Zero-terminated ASCII string data.
10581 *
10582 * On ARM we have two choices: do like gcc does, and LDR from a .word
10583 * with the address, or use an ADR pseudo-op to get the address
10584 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10585 * PC-relative addressing mode and hence has a limited range, which
10586 * makes it not work well with mergeable string sections.
10587 */
10588    .section .rodata.str1.4,"aMS",%progbits,1
10589
10590.LstrBadEntryPoint:
10591    .asciz  "Bad entry point %d\n"
10592.LstrArithmeticException:
10593    .asciz  "Ljava/lang/ArithmeticException;"
10594.LstrArrayStoreException:
10595    .asciz  "Ljava/lang/ArrayStoreException;"
10596.LstrClassCastException:
10597    .asciz  "Ljava/lang/ClassCastException;"
10598.LstrDivideByZero:
10599    .asciz  "divide by zero"
10600.LstrFilledNewArrayNotImpl:
10601    .asciz  "filled-new-array only implemented for objects and 'int'"
10602.LstrInternalError:
10603    .asciz  "Ljava/lang/InternalError;"
10604.LstrInstantiationError:
10605    .asciz  "Ljava/lang/InstantiationError;"
10606.LstrNegativeArraySizeException:
10607    .asciz  "Ljava/lang/NegativeArraySizeException;"
10608.LstrNoSuchMethodError:
10609    .asciz  "Ljava/lang/NoSuchMethodError;"
10610.LstrNullPointerException:
10611    .asciz  "Ljava/lang/NullPointerException;"
10612
10613.LstrLogTag:
10614    .asciz  "mterp"
10615.LstrExceptionNotCaughtLocally:
10616    .asciz  "Exception %s from %s:%d not caught locally\n"
10617
10618.LstrNewline:
10619    .asciz  "\n"
10620.LstrSqueak:
10621    .asciz  "<%d>"
10622.LstrPrintHex:
10623    .asciz  "<0x%x>"
10624.LstrPrintLong:
10625    .asciz  "<%lld>"
10626
10627