InterpAsm-armv5te-vfp.S revision c560e30f68265068bed9eadf174d1e76288d2952
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 desired class resolved from BBBB
7831     *  r9 holds object
7832     */
7833.LOP_CHECK_CAST_fullcheck:
7834    mov     r10, r1                     @ avoid ClassObject getting clobbered
7835    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7836    cmp     r0, #0                      @ failed?
7837    bne     .LOP_CHECK_CAST_okay            @ no, success
7838
7839    @ A cast has failed.  We need to throw a ClassCastException.
7840    EXPORT_PC()                         @ about to throw
7841    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz (actual class)
7842    mov     r1, r10                     @ r1<- desired class
7843    bl      dvmThrowClassCastException
7844    b       common_exceptionThrown
7845
7846    /*
7847     * Resolution required.  This is the least-likely path.
7848     *
7849     *  r2 holds BBBB
7850     *  r9 holds object
7851     */
7852.LOP_CHECK_CAST_resolve:
7853    EXPORT_PC()                         @ resolve() could throw
7854    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7855    mov     r1, r2                      @ r1<- BBBB
7856    mov     r2, #0                      @ r2<- false
7857    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7858    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7859    cmp     r0, #0                      @ got null?
7860    beq     common_exceptionThrown      @ yes, handle exception
7861    mov     r1, r0                      @ r1<- class resolved from BBB
7862    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7863    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7864
7865/* continuation for OP_INSTANCE_OF */
7866
7867    /*
7868     * Trivial test failed, need to perform full check.  This is common.
7869     *  r0 holds obj->clazz
7870     *  r1 holds class resolved from BBBB
7871     *  r9 holds A
7872     */
7873.LOP_INSTANCE_OF_fullcheck:
7874    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7875    @ fall through to OP_INSTANCE_OF_store
7876
7877    /*
7878     * r0 holds boolean result
7879     * r9 holds A
7880     */
7881.LOP_INSTANCE_OF_store:
7882    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7883    SET_VREG(r0, r9)                    @ vA<- r0
7884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7885    GOTO_OPCODE(ip)                     @ jump to next instruction
7886
7887    /*
7888     * Trivial test succeeded, save and bail.
7889     *  r9 holds A
7890     */
7891.LOP_INSTANCE_OF_trivial:
7892    mov     r0, #1                      @ indicate success
7893    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7894    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7895    SET_VREG(r0, r9)                    @ vA<- r0
7896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7897    GOTO_OPCODE(ip)                     @ jump to next instruction
7898
7899    /*
7900     * Resolution required.  This is the least-likely path.
7901     *
7902     *  r3 holds BBBB
7903     *  r9 holds A
7904     */
7905.LOP_INSTANCE_OF_resolve:
7906    EXPORT_PC()                         @ resolve() could throw
7907    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7908    mov     r1, r3                      @ r1<- BBBB
7909    mov     r2, #1                      @ r2<- true
7910    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7911    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7912    cmp     r0, #0                      @ got null?
7913    beq     common_exceptionThrown      @ yes, handle exception
7914    mov     r1, r0                      @ r1<- class resolved from BBB
7915    mov     r3, rINST, lsr #12          @ r3<- B
7916    GET_VREG(r0, r3)                    @ r0<- vB (object)
7917    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7918    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7919
7920/* continuation for OP_NEW_INSTANCE */
7921
7922    .balign 32                          @ minimize cache lines
7923.LOP_NEW_INSTANCE_finish: @ r0=new object
7924    mov     r3, rINST, lsr #8           @ r3<- AA
7925    cmp     r0, #0                      @ failed?
7926    beq     common_exceptionThrown      @ yes, handle the exception
7927    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7929    SET_VREG(r0, r3)                    @ vAA<- r0
7930    GOTO_OPCODE(ip)                     @ jump to next instruction
7931
7932    /*
7933     * Class initialization required.
7934     *
7935     *  r0 holds class object
7936     */
7937.LOP_NEW_INSTANCE_needinit:
7938    mov     r9, r0                      @ save r0
7939    bl      dvmInitClass                @ initialize class
7940    cmp     r0, #0                      @ check boolean result
7941    mov     r0, r9                      @ restore r0
7942    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7943    b       common_exceptionThrown      @ failed, deal with init exception
7944
7945    /*
7946     * Resolution required.  This is the least-likely path.
7947     *
7948     *  r1 holds BBBB
7949     */
7950.LOP_NEW_INSTANCE_resolve:
7951    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7952    mov     r2, #0                      @ r2<- false
7953    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7954    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7955    cmp     r0, #0                      @ got null?
7956    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7957    b       common_exceptionThrown      @ yes, handle exception
7958
7959.LstrInstantiationErrorPtr:
7960    .word   .LstrInstantiationError
7961
7962/* continuation for OP_NEW_ARRAY */
7963
7964
7965    /*
7966     * Resolve class.  (This is an uncommon case.)
7967     *
7968     *  r1 holds array length
7969     *  r2 holds class ref CCCC
7970     */
7971.LOP_NEW_ARRAY_resolve:
7972    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7973    mov     r9, r1                      @ r9<- length (save)
7974    mov     r1, r2                      @ r1<- CCCC
7975    mov     r2, #0                      @ r2<- false
7976    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7977    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7978    cmp     r0, #0                      @ got null?
7979    mov     r1, r9                      @ r1<- length (restore)
7980    beq     common_exceptionThrown      @ yes, handle exception
7981    @ fall through to OP_NEW_ARRAY_finish
7982
7983    /*
7984     * Finish allocation.
7985     *
7986     *  r0 holds class
7987     *  r1 holds array length
7988     */
7989.LOP_NEW_ARRAY_finish:
7990    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7991    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7992    cmp     r0, #0                      @ failed?
7993    mov     r2, rINST, lsr #8           @ r2<- A+
7994    beq     common_exceptionThrown      @ yes, handle the exception
7995    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7996    and     r2, r2, #15                 @ r2<- A
7997    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7998    SET_VREG(r0, r2)                    @ vA<- r0
7999    GOTO_OPCODE(ip)                     @ jump to next instruction
8000
8001/* continuation for OP_FILLED_NEW_ARRAY */
8002
8003    /*
8004     * On entry:
8005     *  r0 holds array class
8006     *  r10 holds AA or BA
8007     */
8008.LOP_FILLED_NEW_ARRAY_continue:
8009    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8010    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8011    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8012    .if     0
8013    mov     r1, r10                     @ r1<- AA (length)
8014    .else
8015    mov     r1, r10, lsr #4             @ r1<- B (length)
8016    .endif
8017    cmp     rINST, #'I'                 @ array of ints?
8018    cmpne   rINST, #'L'                 @ array of objects?
8019    cmpne   rINST, #'['                 @ array of arrays?
8020    mov     r9, r1                      @ save length in r9
8021    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8022    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8023    cmp     r0, #0                      @ null return?
8024    beq     common_exceptionThrown      @ alloc failed, handle exception
8025
8026    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8027    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8028    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8029    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8030    subs    r9, r9, #1                  @ length--, check for neg
8031    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8032    bmi     2f                          @ was zero, bail
8033
8034    @ copy values from registers into the array
8035    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8036    .if     0
8037    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80381:  ldr     r3, [r2], #4                @ r3<- *r2++
8039    subs    r9, r9, #1                  @ count--
8040    str     r3, [r0], #4                @ *contents++ = vX
8041    bpl     1b
8042    @ continue at 2
8043    .else
8044    cmp     r9, #4                      @ length was initially 5?
8045    and     r2, r10, #15                @ r2<- A
8046    bne     1f                          @ <= 4 args, branch
8047    GET_VREG(r3, r2)                    @ r3<- vA
8048    sub     r9, r9, #1                  @ count--
8049    str     r3, [r0, #16]               @ contents[4] = vA
80501:  and     r2, r1, #15                 @ r2<- F/E/D/C
8051    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8052    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8053    subs    r9, r9, #1                  @ count--
8054    str     r3, [r0], #4                @ *contents++ = vX
8055    bpl     1b
8056    @ continue at 2
8057    .endif
8058
80592:
8060    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8061    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8062    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8063    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8064    cmp     r1, #'I'                         @ Is int array?
8065    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8066    GOTO_OPCODE(ip)                          @ execute it
8067
8068    /*
8069     * Throw an exception indicating that we have not implemented this
8070     * mode of filled-new-array.
8071     */
8072.LOP_FILLED_NEW_ARRAY_notimpl:
8073    ldr     r0, .L_strInternalError
8074    ldr     r1, .L_strFilledNewArrayNotImpl
8075    bl      dvmThrowException
8076    b       common_exceptionThrown
8077
8078    .if     (!0)                 @ define in one or the other, not both
8079.L_strFilledNewArrayNotImpl:
8080    .word   .LstrFilledNewArrayNotImpl
8081.L_strInternalError:
8082    .word   .LstrInternalError
8083    .endif
8084
8085/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8086
8087    /*
8088     * On entry:
8089     *  r0 holds array class
8090     *  r10 holds AA or BA
8091     */
8092.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8093    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8094    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8095    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8096    .if     1
8097    mov     r1, r10                     @ r1<- AA (length)
8098    .else
8099    mov     r1, r10, lsr #4             @ r1<- B (length)
8100    .endif
8101    cmp     rINST, #'I'                 @ array of ints?
8102    cmpne   rINST, #'L'                 @ array of objects?
8103    cmpne   rINST, #'['                 @ array of arrays?
8104    mov     r9, r1                      @ save length in r9
8105    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8106    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8107    cmp     r0, #0                      @ null return?
8108    beq     common_exceptionThrown      @ alloc failed, handle exception
8109
8110    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8111    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8112    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8113    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8114    subs    r9, r9, #1                  @ length--, check for neg
8115    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8116    bmi     2f                          @ was zero, bail
8117
8118    @ copy values from registers into the array
8119    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8120    .if     1
8121    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81221:  ldr     r3, [r2], #4                @ r3<- *r2++
8123    subs    r9, r9, #1                  @ count--
8124    str     r3, [r0], #4                @ *contents++ = vX
8125    bpl     1b
8126    @ continue at 2
8127    .else
8128    cmp     r9, #4                      @ length was initially 5?
8129    and     r2, r10, #15                @ r2<- A
8130    bne     1f                          @ <= 4 args, branch
8131    GET_VREG(r3, r2)                    @ r3<- vA
8132    sub     r9, r9, #1                  @ count--
8133    str     r3, [r0, #16]               @ contents[4] = vA
81341:  and     r2, r1, #15                 @ r2<- F/E/D/C
8135    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8136    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8137    subs    r9, r9, #1                  @ count--
8138    str     r3, [r0], #4                @ *contents++ = vX
8139    bpl     1b
8140    @ continue at 2
8141    .endif
8142
81432:
8144    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8145    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8146    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8147    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8148    cmp     r1, #'I'                         @ Is int array?
8149    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8150    GOTO_OPCODE(ip)                          @ execute it
8151
8152    /*
8153     * Throw an exception indicating that we have not implemented this
8154     * mode of filled-new-array.
8155     */
8156.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8157    ldr     r0, .L_strInternalError
8158    ldr     r1, .L_strFilledNewArrayNotImpl
8159    bl      dvmThrowException
8160    b       common_exceptionThrown
8161
8162    .if     (!1)                 @ define in one or the other, not both
8163.L_strFilledNewArrayNotImpl:
8164    .word   .LstrFilledNewArrayNotImpl
8165.L_strInternalError:
8166    .word   .LstrInternalError
8167    .endif
8168
8169/* continuation for OP_CMPL_FLOAT */
8170.LOP_CMPL_FLOAT_finish:
8171    SET_VREG(r0, r9)                    @ vAA<- r0
8172    GOTO_OPCODE(ip)                     @ jump to next instruction
8173
8174/* continuation for OP_CMPG_FLOAT */
8175.LOP_CMPG_FLOAT_finish:
8176    SET_VREG(r0, r9)                    @ vAA<- r0
8177    GOTO_OPCODE(ip)                     @ jump to next instruction
8178
8179/* continuation for OP_CMPL_DOUBLE */
8180.LOP_CMPL_DOUBLE_finish:
8181    SET_VREG(r0, r9)                    @ vAA<- r0
8182    GOTO_OPCODE(ip)                     @ jump to next instruction
8183
8184/* continuation for OP_CMPG_DOUBLE */
8185.LOP_CMPG_DOUBLE_finish:
8186    SET_VREG(r0, r9)                    @ vAA<- r0
8187    GOTO_OPCODE(ip)                     @ jump to next instruction
8188
8189/* continuation for OP_CMP_LONG */
8190
8191.LOP_CMP_LONG_less:
8192    mvn     r1, #0                      @ r1<- -1
8193    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8194    @ instead, we just replicate the tail end.
8195    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8196    SET_VREG(r1, r9)                    @ vAA<- r1
8197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8198    GOTO_OPCODE(ip)                     @ jump to next instruction
8199
8200.LOP_CMP_LONG_greater:
8201    mov     r1, #1                      @ r1<- 1
8202    @ fall through to _finish
8203
8204.LOP_CMP_LONG_finish:
8205    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8206    SET_VREG(r1, r9)                    @ vAA<- r1
8207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8208    GOTO_OPCODE(ip)                     @ jump to next instruction
8209
8210/* continuation for OP_AGET_WIDE */
8211
8212.LOP_AGET_WIDE_finish:
8213    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8214    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8215    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8217    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8218    GOTO_OPCODE(ip)                     @ jump to next instruction
8219
8220/* continuation for OP_APUT_WIDE */
8221
8222.LOP_APUT_WIDE_finish:
8223    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8224    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8226    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8227    GOTO_OPCODE(ip)                     @ jump to next instruction
8228
8229/* continuation for OP_APUT_OBJECT */
8230    /*
8231     * On entry:
8232     *  rINST = vBB (arrayObj)
8233     *  r9 = vAA (obj)
8234     *  r10 = offset into array (vBB + vCC * width)
8235     */
8236.LOP_APUT_OBJECT_finish:
8237    cmp     r9, #0                      @ storing null reference?
8238    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8239    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8240    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8241    bl      dvmCanPutArrayElement       @ test object type vs. array type
8242    cmp     r0, #0                      @ okay?
8243    beq     common_errArrayStore        @ no
8244    mov     r1, rINST                   @ r1<- arrayObj
8245    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8246    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8247    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8248    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8249    str     r9, [r10]                   @ vBB[vCC]<- vAA
8250    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8251    GOTO_OPCODE(ip)                     @ jump to next instruction
8252.LOP_APUT_OBJECT_skip_check:
8253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8254    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8255    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8256    GOTO_OPCODE(ip)                     @ jump to next instruction
8257
8258/* continuation for OP_IGET */
8259
8260    /*
8261     * Currently:
8262     *  r0 holds resolved field
8263     *  r9 holds object
8264     */
8265.LOP_IGET_finish:
8266    @bl      common_squeak0
8267    cmp     r9, #0                      @ check object for null
8268    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8269    beq     common_errNullObject        @ object was null
8270    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8271    @ no-op                             @ acquiring load
8272    mov     r2, rINST, lsr #8           @ r2<- A+
8273    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8274    and     r2, r2, #15                 @ r2<- A
8275    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8276    SET_VREG(r0, r2)                    @ fp[A]<- r0
8277    GOTO_OPCODE(ip)                     @ jump to next instruction
8278
8279/* continuation for OP_IGET_WIDE */
8280
8281    /*
8282     * Currently:
8283     *  r0 holds resolved field
8284     *  r9 holds object
8285     */
8286.LOP_IGET_WIDE_finish:
8287    cmp     r9, #0                      @ check object for null
8288    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8289    beq     common_errNullObject        @ object was null
8290    .if     0
8291    add     r0, r9, r3                  @ r0<- address of field
8292    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8293    .else
8294    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8295    .endif
8296    mov     r2, rINST, lsr #8           @ r2<- A+
8297    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8298    and     r2, r2, #15                 @ r2<- A
8299    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8300    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8301    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8302    GOTO_OPCODE(ip)                     @ jump to next instruction
8303
8304/* continuation for OP_IGET_OBJECT */
8305
8306    /*
8307     * Currently:
8308     *  r0 holds resolved field
8309     *  r9 holds object
8310     */
8311.LOP_IGET_OBJECT_finish:
8312    @bl      common_squeak0
8313    cmp     r9, #0                      @ check object for null
8314    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8315    beq     common_errNullObject        @ object was null
8316    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8317    @ no-op                             @ acquiring load
8318    mov     r2, rINST, lsr #8           @ r2<- A+
8319    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8320    and     r2, r2, #15                 @ r2<- A
8321    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8322    SET_VREG(r0, r2)                    @ fp[A]<- r0
8323    GOTO_OPCODE(ip)                     @ jump to next instruction
8324
8325/* continuation for OP_IGET_BOOLEAN */
8326
8327    /*
8328     * Currently:
8329     *  r0 holds resolved field
8330     *  r9 holds object
8331     */
8332.LOP_IGET_BOOLEAN_finish:
8333    @bl      common_squeak1
8334    cmp     r9, #0                      @ check object for null
8335    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8336    beq     common_errNullObject        @ object was null
8337    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8338    @ no-op                             @ acquiring load
8339    mov     r2, rINST, lsr #8           @ r2<- A+
8340    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8341    and     r2, r2, #15                 @ r2<- A
8342    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8343    SET_VREG(r0, r2)                    @ fp[A]<- r0
8344    GOTO_OPCODE(ip)                     @ jump to next instruction
8345
8346/* continuation for OP_IGET_BYTE */
8347
8348    /*
8349     * Currently:
8350     *  r0 holds resolved field
8351     *  r9 holds object
8352     */
8353.LOP_IGET_BYTE_finish:
8354    @bl      common_squeak2
8355    cmp     r9, #0                      @ check object for null
8356    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8357    beq     common_errNullObject        @ object was null
8358    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8359    @ no-op                             @ acquiring load
8360    mov     r2, rINST, lsr #8           @ r2<- A+
8361    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8362    and     r2, r2, #15                 @ r2<- A
8363    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8364    SET_VREG(r0, r2)                    @ fp[A]<- r0
8365    GOTO_OPCODE(ip)                     @ jump to next instruction
8366
8367/* continuation for OP_IGET_CHAR */
8368
8369    /*
8370     * Currently:
8371     *  r0 holds resolved field
8372     *  r9 holds object
8373     */
8374.LOP_IGET_CHAR_finish:
8375    @bl      common_squeak3
8376    cmp     r9, #0                      @ check object for null
8377    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8378    beq     common_errNullObject        @ object was null
8379    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8380    @ no-op                             @ acquiring load
8381    mov     r2, rINST, lsr #8           @ r2<- A+
8382    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8383    and     r2, r2, #15                 @ r2<- A
8384    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8385    SET_VREG(r0, r2)                    @ fp[A]<- r0
8386    GOTO_OPCODE(ip)                     @ jump to next instruction
8387
8388/* continuation for OP_IGET_SHORT */
8389
8390    /*
8391     * Currently:
8392     *  r0 holds resolved field
8393     *  r9 holds object
8394     */
8395.LOP_IGET_SHORT_finish:
8396    @bl      common_squeak4
8397    cmp     r9, #0                      @ check object for null
8398    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8399    beq     common_errNullObject        @ object was null
8400    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8401    @ no-op                             @ acquiring load
8402    mov     r2, rINST, lsr #8           @ r2<- A+
8403    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8404    and     r2, r2, #15                 @ r2<- A
8405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8406    SET_VREG(r0, r2)                    @ fp[A]<- r0
8407    GOTO_OPCODE(ip)                     @ jump to next instruction
8408
8409/* continuation for OP_IPUT */
8410
8411    /*
8412     * Currently:
8413     *  r0 holds resolved field
8414     *  r9 holds object
8415     */
8416.LOP_IPUT_finish:
8417    @bl      common_squeak0
8418    mov     r1, rINST, lsr #8           @ r1<- A+
8419    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8420    and     r1, r1, #15                 @ r1<- A
8421    cmp     r9, #0                      @ check object for null
8422    GET_VREG(r0, r1)                    @ r0<- fp[A]
8423    beq     common_errNullObject        @ object was null
8424    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8426    @ no-op                             @ releasing store
8427    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8428    GOTO_OPCODE(ip)                     @ jump to next instruction
8429
8430/* continuation for OP_IPUT_WIDE */
8431
8432    /*
8433     * Currently:
8434     *  r0 holds resolved field
8435     *  r9 holds object
8436     */
8437.LOP_IPUT_WIDE_finish:
8438    mov     r2, rINST, lsr #8           @ r2<- A+
8439    cmp     r9, #0                      @ check object for null
8440    and     r2, r2, #15                 @ r2<- A
8441    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8442    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8443    beq     common_errNullObject        @ object was null
8444    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8445    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8446    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8447    .if     0
8448    add     r2, r9, r3                  @ r2<- target address
8449    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8450    .else
8451    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8452    .endif
8453    GOTO_OPCODE(r10)                    @ jump to next instruction
8454
8455/* continuation for OP_IPUT_OBJECT */
8456
8457    /*
8458     * Currently:
8459     *  r0 holds resolved field
8460     *  r9 holds object
8461     */
8462.LOP_IPUT_OBJECT_finish:
8463    @bl      common_squeak0
8464    mov     r1, rINST, lsr #8           @ r1<- A+
8465    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8466    and     r1, r1, #15                 @ r1<- A
8467    cmp     r9, #0                      @ check object for null
8468    GET_VREG(r0, r1)                    @ r0<- fp[A]
8469    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8470    beq     common_errNullObject        @ object was null
8471    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8472    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8473    @ no-op                             @ releasing store
8474    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
8475    cmp     r0, #0                      @ stored a null reference?
8476    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8477    GOTO_OPCODE(ip)                     @ jump to next instruction
8478
8479/* continuation for OP_IPUT_BOOLEAN */
8480
8481    /*
8482     * Currently:
8483     *  r0 holds resolved field
8484     *  r9 holds object
8485     */
8486.LOP_IPUT_BOOLEAN_finish:
8487    @bl      common_squeak1
8488    mov     r1, rINST, lsr #8           @ r1<- A+
8489    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8490    and     r1, r1, #15                 @ r1<- A
8491    cmp     r9, #0                      @ check object for null
8492    GET_VREG(r0, r1)                    @ r0<- fp[A]
8493    beq     common_errNullObject        @ object was null
8494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8496    @ no-op                             @ releasing store
8497    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8498    GOTO_OPCODE(ip)                     @ jump to next instruction
8499
8500/* continuation for OP_IPUT_BYTE */
8501
8502    /*
8503     * Currently:
8504     *  r0 holds resolved field
8505     *  r9 holds object
8506     */
8507.LOP_IPUT_BYTE_finish:
8508    @bl      common_squeak2
8509    mov     r1, rINST, lsr #8           @ r1<- A+
8510    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8511    and     r1, r1, #15                 @ r1<- A
8512    cmp     r9, #0                      @ check object for null
8513    GET_VREG(r0, r1)                    @ r0<- fp[A]
8514    beq     common_errNullObject        @ object was null
8515    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8517    @ no-op                             @ releasing store
8518    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8519    GOTO_OPCODE(ip)                     @ jump to next instruction
8520
8521/* continuation for OP_IPUT_CHAR */
8522
8523    /*
8524     * Currently:
8525     *  r0 holds resolved field
8526     *  r9 holds object
8527     */
8528.LOP_IPUT_CHAR_finish:
8529    @bl      common_squeak3
8530    mov     r1, rINST, lsr #8           @ r1<- A+
8531    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8532    and     r1, r1, #15                 @ r1<- A
8533    cmp     r9, #0                      @ check object for null
8534    GET_VREG(r0, r1)                    @ r0<- fp[A]
8535    beq     common_errNullObject        @ object was null
8536    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8538    @ no-op                             @ releasing store
8539    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8540    GOTO_OPCODE(ip)                     @ jump to next instruction
8541
8542/* continuation for OP_IPUT_SHORT */
8543
8544    /*
8545     * Currently:
8546     *  r0 holds resolved field
8547     *  r9 holds object
8548     */
8549.LOP_IPUT_SHORT_finish:
8550    @bl      common_squeak4
8551    mov     r1, rINST, lsr #8           @ r1<- A+
8552    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8553    and     r1, r1, #15                 @ r1<- A
8554    cmp     r9, #0                      @ check object for null
8555    GET_VREG(r0, r1)                    @ r0<- fp[A]
8556    beq     common_errNullObject        @ object was null
8557    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8559    @ no-op                             @ releasing store
8560    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8561    GOTO_OPCODE(ip)                     @ jump to next instruction
8562
8563/* continuation for OP_SGET */
8564
8565    /*
8566     * Continuation if the field has not yet been resolved.
8567     *  r1: BBBB field ref
8568     */
8569.LOP_SGET_resolve:
8570    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8571    EXPORT_PC()                         @ resolve() could throw, so export now
8572    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8573    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8574    cmp     r0, #0                      @ success?
8575    bne     .LOP_SGET_finish          @ yes, finish
8576    b       common_exceptionThrown      @ no, handle exception
8577
8578/* continuation for OP_SGET_WIDE */
8579
8580    /*
8581     * Continuation if the field has not yet been resolved.
8582     *  r1: BBBB field ref
8583     *
8584     * Returns StaticField pointer in r0.
8585     */
8586.LOP_SGET_WIDE_resolve:
8587    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8588    EXPORT_PC()                         @ resolve() could throw, so export now
8589    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8590    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8591    cmp     r0, #0                      @ success?
8592    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8593    b       common_exceptionThrown      @ no, handle exception
8594
8595/* continuation for OP_SGET_OBJECT */
8596
8597    /*
8598     * Continuation if the field has not yet been resolved.
8599     *  r1: BBBB field ref
8600     */
8601.LOP_SGET_OBJECT_resolve:
8602    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8603    EXPORT_PC()                         @ resolve() could throw, so export now
8604    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8605    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8606    cmp     r0, #0                      @ success?
8607    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8608    b       common_exceptionThrown      @ no, handle exception
8609
8610/* continuation for OP_SGET_BOOLEAN */
8611
8612    /*
8613     * Continuation if the field has not yet been resolved.
8614     *  r1: BBBB field ref
8615     */
8616.LOP_SGET_BOOLEAN_resolve:
8617    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8618    EXPORT_PC()                         @ resolve() could throw, so export now
8619    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8620    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8621    cmp     r0, #0                      @ success?
8622    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8623    b       common_exceptionThrown      @ no, handle exception
8624
8625/* continuation for OP_SGET_BYTE */
8626
8627    /*
8628     * Continuation if the field has not yet been resolved.
8629     *  r1: BBBB field ref
8630     */
8631.LOP_SGET_BYTE_resolve:
8632    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8633    EXPORT_PC()                         @ resolve() could throw, so export now
8634    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8635    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8636    cmp     r0, #0                      @ success?
8637    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8638    b       common_exceptionThrown      @ no, handle exception
8639
8640/* continuation for OP_SGET_CHAR */
8641
8642    /*
8643     * Continuation if the field has not yet been resolved.
8644     *  r1: BBBB field ref
8645     */
8646.LOP_SGET_CHAR_resolve:
8647    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8648    EXPORT_PC()                         @ resolve() could throw, so export now
8649    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8650    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8651    cmp     r0, #0                      @ success?
8652    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8653    b       common_exceptionThrown      @ no, handle exception
8654
8655/* continuation for OP_SGET_SHORT */
8656
8657    /*
8658     * Continuation if the field has not yet been resolved.
8659     *  r1: BBBB field ref
8660     */
8661.LOP_SGET_SHORT_resolve:
8662    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8663    EXPORT_PC()                         @ resolve() could throw, so export now
8664    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8665    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8666    cmp     r0, #0                      @ success?
8667    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8668    b       common_exceptionThrown      @ no, handle exception
8669
8670/* continuation for OP_SPUT */
8671
8672    /*
8673     * Continuation if the field has not yet been resolved.
8674     *  r1: BBBB field ref
8675     */
8676.LOP_SPUT_resolve:
8677    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8678    EXPORT_PC()                         @ resolve() could throw, so export now
8679    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8680    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8681    cmp     r0, #0                      @ success?
8682    bne     .LOP_SPUT_finish          @ yes, finish
8683    b       common_exceptionThrown      @ no, handle exception
8684
8685/* continuation for OP_SPUT_WIDE */
8686
8687    /*
8688     * Continuation if the field has not yet been resolved.
8689     *  r1: BBBB field ref
8690     *  r9: &fp[AA]
8691     *
8692     * Returns StaticField pointer in r2.
8693     */
8694.LOP_SPUT_WIDE_resolve:
8695    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8696    EXPORT_PC()                         @ resolve() could throw, so export now
8697    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8698    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8699    cmp     r0, #0                      @ success?
8700    mov     r2, r0                      @ copy to r2
8701    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8702    b       common_exceptionThrown      @ no, handle exception
8703
8704/* continuation for OP_SPUT_OBJECT */
8705.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8706    mov     r2, rINST, lsr #8           @ r2<- AA
8707    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8708    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8709    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8710    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
8711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8712    @ no-op                             @ releasing store
8713    str     r1, [r0, #offStaticField_value]  @ field<- vAA
8714    cmp     r1, #0                      @ stored a null object?
8715    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
8716    GOTO_OPCODE(ip)                     @ jump to next instruction
8717
8718/* continuation for OP_SPUT_BOOLEAN */
8719
8720    /*
8721     * Continuation if the field has not yet been resolved.
8722     *  r1: BBBB field ref
8723     */
8724.LOP_SPUT_BOOLEAN_resolve:
8725    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8726    EXPORT_PC()                         @ resolve() could throw, so export now
8727    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8728    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8729    cmp     r0, #0                      @ success?
8730    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8731    b       common_exceptionThrown      @ no, handle exception
8732
8733/* continuation for OP_SPUT_BYTE */
8734
8735    /*
8736     * Continuation if the field has not yet been resolved.
8737     *  r1: BBBB field ref
8738     */
8739.LOP_SPUT_BYTE_resolve:
8740    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8741    EXPORT_PC()                         @ resolve() could throw, so export now
8742    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8743    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8744    cmp     r0, #0                      @ success?
8745    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8746    b       common_exceptionThrown      @ no, handle exception
8747
8748/* continuation for OP_SPUT_CHAR */
8749
8750    /*
8751     * Continuation if the field has not yet been resolved.
8752     *  r1: BBBB field ref
8753     */
8754.LOP_SPUT_CHAR_resolve:
8755    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8756    EXPORT_PC()                         @ resolve() could throw, so export now
8757    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8758    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8759    cmp     r0, #0                      @ success?
8760    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8761    b       common_exceptionThrown      @ no, handle exception
8762
8763/* continuation for OP_SPUT_SHORT */
8764
8765    /*
8766     * Continuation if the field has not yet been resolved.
8767     *  r1: BBBB field ref
8768     */
8769.LOP_SPUT_SHORT_resolve:
8770    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8771    EXPORT_PC()                         @ resolve() could throw, so export now
8772    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8773    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8774    cmp     r0, #0                      @ success?
8775    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8776    b       common_exceptionThrown      @ no, handle exception
8777
8778/* continuation for OP_INVOKE_VIRTUAL */
8779
8780    /*
8781     * At this point:
8782     *  r0 = resolved base method
8783     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8784     */
8785.LOP_INVOKE_VIRTUAL_continue:
8786    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8787    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8788    cmp     r1, #0                      @ is "this" null?
8789    beq     common_errNullObject        @ null "this", throw exception
8790    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8791    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8792    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8793    bl      common_invokeMethodNoRange @ continue on
8794
8795/* continuation for OP_INVOKE_SUPER */
8796
8797    /*
8798     * At this point:
8799     *  r0 = resolved base method
8800     *  r9 = method->clazz
8801     */
8802.LOP_INVOKE_SUPER_continue:
8803    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8804    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8805    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8806    EXPORT_PC()                         @ must export for invoke
8807    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8808    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8809    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8810    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8811    bl      common_invokeMethodNoRange @ continue on
8812
8813.LOP_INVOKE_SUPER_resolve:
8814    mov     r0, r9                      @ r0<- method->clazz
8815    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8816    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8817    cmp     r0, #0                      @ got null?
8818    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8819    b       common_exceptionThrown      @ yes, handle exception
8820
8821    /*
8822     * Throw a NoSuchMethodError with the method name as the message.
8823     *  r0 = resolved base method
8824     */
8825.LOP_INVOKE_SUPER_nsm:
8826    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8827    b       common_errNoSuchMethod
8828
8829/* continuation for OP_INVOKE_DIRECT */
8830
8831    /*
8832     * On entry:
8833     *  r1 = reference (BBBB or CCCC)
8834     *  r10 = "this" register
8835     */
8836.LOP_INVOKE_DIRECT_resolve:
8837    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8838    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8839    mov     r2, #METHOD_DIRECT          @ resolver method type
8840    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8841    cmp     r0, #0                      @ got null?
8842    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8843    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8844    b       common_exceptionThrown      @ yes, handle exception
8845
8846/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8847
8848    /*
8849     * At this point:
8850     *  r0 = resolved base method
8851     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8852     */
8853.LOP_INVOKE_VIRTUAL_RANGE_continue:
8854    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8855    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8856    cmp     r1, #0                      @ is "this" null?
8857    beq     common_errNullObject        @ null "this", throw exception
8858    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8859    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8860    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8861    bl      common_invokeMethodRange @ continue on
8862
8863/* continuation for OP_INVOKE_SUPER_RANGE */
8864
8865    /*
8866     * At this point:
8867     *  r0 = resolved base method
8868     *  r9 = method->clazz
8869     */
8870.LOP_INVOKE_SUPER_RANGE_continue:
8871    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8872    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8873    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8874    EXPORT_PC()                         @ must export for invoke
8875    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8876    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8877    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8878    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8879    bl      common_invokeMethodRange @ continue on
8880
8881.LOP_INVOKE_SUPER_RANGE_resolve:
8882    mov     r0, r9                      @ r0<- method->clazz
8883    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8884    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8885    cmp     r0, #0                      @ got null?
8886    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8887    b       common_exceptionThrown      @ yes, handle exception
8888
8889    /*
8890     * Throw a NoSuchMethodError with the method name as the message.
8891     *  r0 = resolved base method
8892     */
8893.LOP_INVOKE_SUPER_RANGE_nsm:
8894    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8895    b       common_errNoSuchMethod
8896
8897/* continuation for OP_INVOKE_DIRECT_RANGE */
8898
8899    /*
8900     * On entry:
8901     *  r1 = reference (BBBB or CCCC)
8902     *  r10 = "this" register
8903     */
8904.LOP_INVOKE_DIRECT_RANGE_resolve:
8905    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8906    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8907    mov     r2, #METHOD_DIRECT          @ resolver method type
8908    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8909    cmp     r0, #0                      @ got null?
8910    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8911    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8912    b       common_exceptionThrown      @ yes, handle exception
8913
8914/* continuation for OP_FLOAT_TO_LONG */
8915/*
8916 * Convert the float in r0 to a long in r0/r1.
8917 *
8918 * We have to clip values to long min/max per the specification.  The
8919 * expected common case is a "reasonable" value that converts directly
8920 * to modest integer.  The EABI convert function isn't doing this for us.
8921 */
8922f2l_doconv:
8923    stmfd   sp!, {r4, lr}
8924    mov     r1, #0x5f000000             @ (float)maxlong
8925    mov     r4, r0
8926    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8927    cmp     r0, #0                      @ nonzero == yes
8928    mvnne   r0, #0                      @ return maxlong (7fffffff)
8929    mvnne   r1, #0x80000000
8930    ldmnefd sp!, {r4, pc}
8931
8932    mov     r0, r4                      @ recover arg
8933    mov     r1, #0xdf000000             @ (float)minlong
8934    bl      __aeabi_fcmple              @ is arg <= minlong?
8935    cmp     r0, #0                      @ nonzero == yes
8936    movne   r0, #0                      @ return minlong (80000000)
8937    movne   r1, #0x80000000
8938    ldmnefd sp!, {r4, pc}
8939
8940    mov     r0, r4                      @ recover arg
8941    mov     r1, r4
8942    bl      __aeabi_fcmpeq              @ is arg == self?
8943    cmp     r0, #0                      @ zero == no
8944    moveq   r1, #0                      @ return zero for NaN
8945    ldmeqfd sp!, {r4, pc}
8946
8947    mov     r0, r4                      @ recover arg
8948    bl      __aeabi_f2lz                @ convert float to long
8949    ldmfd   sp!, {r4, pc}
8950
8951/* continuation for OP_DOUBLE_TO_LONG */
8952/*
8953 * Convert the double in r0/r1 to a long in r0/r1.
8954 *
8955 * We have to clip values to long min/max per the specification.  The
8956 * expected common case is a "reasonable" value that converts directly
8957 * to modest integer.  The EABI convert function isn't doing this for us.
8958 */
8959d2l_doconv:
8960    stmfd   sp!, {r4, r5, lr}           @ save regs
8961    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8962    add     r3, #0x00e00000             @  0x43e00000
8963    mov     r2, #0                      @ maxlong, as a double (low word)
8964    sub     sp, sp, #4                  @ align for EABI
8965    mov     r4, r0                      @ save a copy of r0
8966    mov     r5, r1                      @  and r1
8967    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8968    cmp     r0, #0                      @ nonzero == yes
8969    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8970    mvnne   r1, #0x80000000
8971    bne     1f
8972
8973    mov     r0, r4                      @ recover arg
8974    mov     r1, r5
8975    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8976    add     r3, #0x00e00000             @  0xc3e00000
8977    mov     r2, #0                      @ minlong, as a double (low word)
8978    bl      __aeabi_dcmple              @ is arg <= minlong?
8979    cmp     r0, #0                      @ nonzero == yes
8980    movne   r0, #0                      @ return minlong (8000000000000000)
8981    movne   r1, #0x80000000
8982    bne     1f
8983
8984    mov     r0, r4                      @ recover arg
8985    mov     r1, r5
8986    mov     r2, r4                      @ compare against self
8987    mov     r3, r5
8988    bl      __aeabi_dcmpeq              @ is arg == self?
8989    cmp     r0, #0                      @ zero == no
8990    moveq   r1, #0                      @ return zero for NaN
8991    beq     1f
8992
8993    mov     r0, r4                      @ recover arg
8994    mov     r1, r5
8995    bl      __aeabi_d2lz                @ convert double to long
8996
89971:
8998    add     sp, sp, #4
8999    ldmfd   sp!, {r4, r5, pc}
9000
9001/* continuation for OP_MUL_LONG */
9002
9003.LOP_MUL_LONG_finish:
9004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9005    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9006    GOTO_OPCODE(ip)                     @ jump to next instruction
9007
9008/* continuation for OP_SHL_LONG */
9009
9010.LOP_SHL_LONG_finish:
9011    mov     r0, r0, asl r2              @  r0<- r0 << r2
9012    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9013    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9014    GOTO_OPCODE(ip)                     @ jump to next instruction
9015
9016/* continuation for OP_SHR_LONG */
9017
9018.LOP_SHR_LONG_finish:
9019    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9020    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9021    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9022    GOTO_OPCODE(ip)                     @ jump to next instruction
9023
9024/* continuation for OP_USHR_LONG */
9025
9026.LOP_USHR_LONG_finish:
9027    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9028    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9029    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9030    GOTO_OPCODE(ip)                     @ jump to next instruction
9031
9032/* continuation for OP_SHL_LONG_2ADDR */
9033
9034.LOP_SHL_LONG_2ADDR_finish:
9035    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9036    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9037    GOTO_OPCODE(ip)                     @ jump to next instruction
9038
9039/* continuation for OP_SHR_LONG_2ADDR */
9040
9041.LOP_SHR_LONG_2ADDR_finish:
9042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9043    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9044    GOTO_OPCODE(ip)                     @ jump to next instruction
9045
9046/* continuation for OP_USHR_LONG_2ADDR */
9047
9048.LOP_USHR_LONG_2ADDR_finish:
9049    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9050    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9051    GOTO_OPCODE(ip)                     @ jump to next instruction
9052
9053/* continuation for OP_IGET_VOLATILE */
9054
9055    /*
9056     * Currently:
9057     *  r0 holds resolved field
9058     *  r9 holds object
9059     */
9060.LOP_IGET_VOLATILE_finish:
9061    @bl      common_squeak0
9062    cmp     r9, #0                      @ check object for null
9063    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9064    beq     common_errNullObject        @ object was null
9065    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9066    SMP_DMB                            @ acquiring load
9067    mov     r2, rINST, lsr #8           @ r2<- A+
9068    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9069    and     r2, r2, #15                 @ r2<- A
9070    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9071    SET_VREG(r0, r2)                    @ fp[A]<- r0
9072    GOTO_OPCODE(ip)                     @ jump to next instruction
9073
9074/* continuation for OP_IPUT_VOLATILE */
9075
9076    /*
9077     * Currently:
9078     *  r0 holds resolved field
9079     *  r9 holds object
9080     */
9081.LOP_IPUT_VOLATILE_finish:
9082    @bl      common_squeak0
9083    mov     r1, rINST, lsr #8           @ r1<- A+
9084    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9085    and     r1, r1, #15                 @ r1<- A
9086    cmp     r9, #0                      @ check object for null
9087    GET_VREG(r0, r1)                    @ r0<- fp[A]
9088    beq     common_errNullObject        @ object was null
9089    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9090    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9091    SMP_DMB                            @ releasing store
9092    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9093    GOTO_OPCODE(ip)                     @ jump to next instruction
9094
9095/* continuation for OP_SGET_VOLATILE */
9096
9097    /*
9098     * Continuation if the field has not yet been resolved.
9099     *  r1: BBBB field ref
9100     */
9101.LOP_SGET_VOLATILE_resolve:
9102    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9103    EXPORT_PC()                         @ resolve() could throw, so export now
9104    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9105    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9106    cmp     r0, #0                      @ success?
9107    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9108    b       common_exceptionThrown      @ no, handle exception
9109
9110/* continuation for OP_SPUT_VOLATILE */
9111
9112    /*
9113     * Continuation if the field has not yet been resolved.
9114     *  r1: BBBB field ref
9115     */
9116.LOP_SPUT_VOLATILE_resolve:
9117    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9118    EXPORT_PC()                         @ resolve() could throw, so export now
9119    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9120    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9121    cmp     r0, #0                      @ success?
9122    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9123    b       common_exceptionThrown      @ no, handle exception
9124
9125/* continuation for OP_IGET_OBJECT_VOLATILE */
9126
9127    /*
9128     * Currently:
9129     *  r0 holds resolved field
9130     *  r9 holds object
9131     */
9132.LOP_IGET_OBJECT_VOLATILE_finish:
9133    @bl      common_squeak0
9134    cmp     r9, #0                      @ check object for null
9135    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9136    beq     common_errNullObject        @ object was null
9137    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9138    SMP_DMB                            @ acquiring load
9139    mov     r2, rINST, lsr #8           @ r2<- A+
9140    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9141    and     r2, r2, #15                 @ r2<- A
9142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9143    SET_VREG(r0, r2)                    @ fp[A]<- r0
9144    GOTO_OPCODE(ip)                     @ jump to next instruction
9145
9146/* continuation for OP_IGET_WIDE_VOLATILE */
9147
9148    /*
9149     * Currently:
9150     *  r0 holds resolved field
9151     *  r9 holds object
9152     */
9153.LOP_IGET_WIDE_VOLATILE_finish:
9154    cmp     r9, #0                      @ check object for null
9155    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9156    beq     common_errNullObject        @ object was null
9157    .if     1
9158    add     r0, r9, r3                  @ r0<- address of field
9159    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9160    .else
9161    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9162    .endif
9163    mov     r2, rINST, lsr #8           @ r2<- A+
9164    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9165    and     r2, r2, #15                 @ r2<- A
9166    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9168    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9169    GOTO_OPCODE(ip)                     @ jump to next instruction
9170
9171/* continuation for OP_IPUT_WIDE_VOLATILE */
9172
9173    /*
9174     * Currently:
9175     *  r0 holds resolved field
9176     *  r9 holds object
9177     */
9178.LOP_IPUT_WIDE_VOLATILE_finish:
9179    mov     r2, rINST, lsr #8           @ r2<- A+
9180    cmp     r9, #0                      @ check object for null
9181    and     r2, r2, #15                 @ r2<- A
9182    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9183    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9184    beq     common_errNullObject        @ object was null
9185    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9186    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9187    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9188    .if     1
9189    add     r2, r9, r3                  @ r2<- target address
9190    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9191    .else
9192    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9193    .endif
9194    GOTO_OPCODE(r10)                    @ jump to next instruction
9195
9196/* continuation for OP_SGET_WIDE_VOLATILE */
9197
9198    /*
9199     * Continuation if the field has not yet been resolved.
9200     *  r1: BBBB field ref
9201     *
9202     * Returns StaticField pointer in r0.
9203     */
9204.LOP_SGET_WIDE_VOLATILE_resolve:
9205    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9206    EXPORT_PC()                         @ resolve() could throw, so export now
9207    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9208    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9209    cmp     r0, #0                      @ success?
9210    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9211    b       common_exceptionThrown      @ no, handle exception
9212
9213/* continuation for OP_SPUT_WIDE_VOLATILE */
9214
9215    /*
9216     * Continuation if the field has not yet been resolved.
9217     *  r1: BBBB field ref
9218     *  r9: &fp[AA]
9219     *
9220     * Returns StaticField pointer in r2.
9221     */
9222.LOP_SPUT_WIDE_VOLATILE_resolve:
9223    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9224    EXPORT_PC()                         @ resolve() could throw, so export now
9225    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9226    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9227    cmp     r0, #0                      @ success?
9228    mov     r2, r0                      @ copy to r2
9229    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9230    b       common_exceptionThrown      @ no, handle exception
9231
9232/* continuation for OP_EXECUTE_INLINE */
9233
9234    /*
9235     * Extract args, call function.
9236     *  r0 = #of args (0-4)
9237     *  r10 = call index
9238     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9239     *
9240     * Other ideas:
9241     * - Use a jump table from the main piece to jump directly into the
9242     *   AND/LDR pairs.  Costs a data load, saves a branch.
9243     * - Have five separate pieces that do the loading, so we can work the
9244     *   interleave a little better.  Increases code size.
9245     */
9246.LOP_EXECUTE_INLINE_continue:
9247    rsb     r0, r0, #4                  @ r0<- 4-r0
9248    FETCH(r9, 2)                        @ r9<- FEDC
9249    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9250    bl      common_abort                @ (skipped due to ARM prefetch)
92514:  and     ip, r9, #0xf000             @ isolate F
9252    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92533:  and     ip, r9, #0x0f00             @ isolate E
9254    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92552:  and     ip, r9, #0x00f0             @ isolate D
9256    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92571:  and     ip, r9, #0x000f             @ isolate C
9258    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92590:
9260    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9261    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9262    @ (not reached)
9263
9264.LOP_EXECUTE_INLINE_table:
9265    .word   gDvmInlineOpsTable
9266
9267/* continuation for OP_EXECUTE_INLINE_RANGE */
9268
9269    /*
9270     * Extract args, call function.
9271     *  r0 = #of args (0-4)
9272     *  r10 = call index
9273     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9274     */
9275.LOP_EXECUTE_INLINE_RANGE_continue:
9276    rsb     r0, r0, #4                  @ r0<- 4-r0
9277    FETCH(r9, 2)                        @ r9<- CCCC
9278    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9279    bl      common_abort                @ (skipped due to ARM prefetch)
92804:  add     ip, r9, #3                  @ base+3
9281    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92823:  add     ip, r9, #2                  @ base+2
9283    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92842:  add     ip, r9, #1                  @ base+1
9285    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92861:  add     ip, r9, #0                  @ (nop)
9287    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92880:
9289    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9290    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9291    @ (not reached)
9292
9293.LOP_EXECUTE_INLINE_RANGE_table:
9294    .word   gDvmInlineOpsTable
9295
9296/* continuation for OP_IPUT_OBJECT_VOLATILE */
9297
9298    /*
9299     * Currently:
9300     *  r0 holds resolved field
9301     *  r9 holds object
9302     */
9303.LOP_IPUT_OBJECT_VOLATILE_finish:
9304    @bl      common_squeak0
9305    mov     r1, rINST, lsr #8           @ r1<- A+
9306    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9307    and     r1, r1, #15                 @ r1<- A
9308    cmp     r9, #0                      @ check object for null
9309    GET_VREG(r0, r1)                    @ r0<- fp[A]
9310    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9311    beq     common_errNullObject        @ object was null
9312    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9313    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9314    SMP_DMB                            @ releasing store
9315    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
9316    cmp     r0, #0                      @ stored a null reference?
9317    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9318    GOTO_OPCODE(ip)                     @ jump to next instruction
9319
9320/* continuation for OP_SGET_OBJECT_VOLATILE */
9321
9322    /*
9323     * Continuation if the field has not yet been resolved.
9324     *  r1: BBBB field ref
9325     */
9326.LOP_SGET_OBJECT_VOLATILE_resolve:
9327    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9328    EXPORT_PC()                         @ resolve() could throw, so export now
9329    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9330    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9331    cmp     r0, #0                      @ success?
9332    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9333    b       common_exceptionThrown      @ no, handle exception
9334
9335/* continuation for OP_SPUT_OBJECT_VOLATILE */
9336.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9337    mov     r2, rINST, lsr #8           @ r2<- AA
9338    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9339    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9340    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9341    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9342    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9343    SMP_DMB                            @ releasing store
9344    str     r1, [r0, #offStaticField_value]  @ field<- vAA
9345    cmp     r1, #0                      @ stored a null object?
9346    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9347    GOTO_OPCODE(ip)                     @ jump to next instruction
9348
9349    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9350    .global dvmAsmSisterEnd
9351dvmAsmSisterEnd:
9352
9353/* File: armv5te/footer.S */
9354
9355/*
9356 * ===========================================================================
9357 *  Common subroutines and data
9358 * ===========================================================================
9359 */
9360
9361
9362
9363    .text
9364    .align  2
9365
9366#if defined(WITH_JIT)
9367#if defined(WITH_SELF_VERIFICATION)
9368    .global dvmJitToInterpPunt
9369dvmJitToInterpPunt:
9370    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9371    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9372    mov    r3, #0
9373    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9374    b      jitSVShadowRunEnd            @ doesn't return
9375
9376    .global dvmJitToInterpSingleStep
9377dvmJitToInterpSingleStep:
9378    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9379    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9380    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9381    b      jitSVShadowRunEnd            @ doesn't return
9382
9383    .global dvmJitToInterpNoChainNoProfile
9384dvmJitToInterpNoChainNoProfile:
9385    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9386    mov    r0,rPC                       @ pass our target PC
9387    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9388    mov    r3, #0                       @ 0 means !inJitCodeCache
9389    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9390    b      jitSVShadowRunEnd            @ doesn't return
9391
9392    .global dvmJitToInterpTraceSelectNoChain
9393dvmJitToInterpTraceSelectNoChain:
9394    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9395    mov    r0,rPC                       @ pass our target PC
9396    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9397    mov    r3, #0                       @ 0 means !inJitCodeCache
9398    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9399    b      jitSVShadowRunEnd            @ doesn't return
9400
9401    .global dvmJitToInterpTraceSelect
9402dvmJitToInterpTraceSelect:
9403    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9404    ldr    r0,[lr, #-1]                 @ pass our target PC
9405    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9406    mov    r3, #0                       @ 0 means !inJitCodeCache
9407    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9408    b      jitSVShadowRunEnd            @ doesn't return
9409
9410    .global dvmJitToInterpBackwardBranch
9411dvmJitToInterpBackwardBranch:
9412    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9413    ldr    r0,[lr, #-1]                 @ pass our target PC
9414    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9415    mov    r3, #0                       @ 0 means !inJitCodeCache
9416    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9417    b      jitSVShadowRunEnd            @ doesn't return
9418
9419    .global dvmJitToInterpNormal
9420dvmJitToInterpNormal:
9421    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9422    ldr    r0,[lr, #-1]                 @ pass our target PC
9423    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9424    mov    r3, #0                       @ 0 means !inJitCodeCache
9425    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9426    b      jitSVShadowRunEnd            @ doesn't return
9427
9428    .global dvmJitToInterpNoChain
9429dvmJitToInterpNoChain:
9430    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9431    mov    r0,rPC                       @ pass our target PC
9432    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9433    mov    r3, #0                       @ 0 means !inJitCodeCache
9434    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9435    b      jitSVShadowRunEnd            @ doesn't return
9436#else
9437/*
9438 * Return from the translation cache to the interpreter when the compiler is
9439 * having issues translating/executing a Dalvik instruction. We have to skip
9440 * the code cache lookup otherwise it is possible to indefinitely bouce
9441 * between the interpreter and the code cache if the instruction that fails
9442 * to be compiled happens to be at a trace start.
9443 */
9444    .global dvmJitToInterpPunt
9445dvmJitToInterpPunt:
9446    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9447    mov    rPC, r0
9448#if defined(WITH_JIT_TUNING)
9449    mov    r0,lr
9450    bl     dvmBumpPunt;
9451#endif
9452    EXPORT_PC()
9453    mov    r0, #0
9454    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9455    adrl   rIBASE, dvmAsmInstructionStart
9456    FETCH_INST()
9457    GET_INST_OPCODE(ip)
9458    GOTO_OPCODE(ip)
9459
9460/*
9461 * Return to the interpreter to handle a single instruction.
9462 * On entry:
9463 *    r0 <= PC
9464 *    r1 <= PC of resume instruction
9465 *    lr <= resume point in translation
9466 */
9467    .global dvmJitToInterpSingleStep
9468dvmJitToInterpSingleStep:
9469    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9470    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9471    mov    r1,#kInterpEntryInstr
9472    @ enum is 4 byte in aapcs-EABI
9473    str    r1, [rGLUE, #offGlue_entryPoint]
9474    mov    rPC,r0
9475    EXPORT_PC()
9476
9477    adrl   rIBASE, dvmAsmInstructionStart
9478    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9479    str    r2,[rGLUE,#offGlue_jitState]
9480    mov    r1,#1                  @ set changeInterp to bail to debug interp
9481    b      common_gotoBail
9482
9483/*
9484 * Return from the translation cache and immediately request
9485 * a translation for the exit target.  Commonly used for callees.
9486 */
9487    .global dvmJitToInterpTraceSelectNoChain
9488dvmJitToInterpTraceSelectNoChain:
9489#if defined(WITH_JIT_TUNING)
9490    bl     dvmBumpNoChain
9491#endif
9492    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9493    mov    r0,rPC
9494    bl     dvmJitGetCodeAddr        @ Is there a translation?
9495    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9496    mov    r1, rPC                  @ arg1 of translation may need this
9497    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9498    cmp    r0,#0                    @ !0 means translation exists
9499    bxne   r0                       @ continue native execution if so
9500    b      2f                       @ branch over to use the interpreter
9501
9502/*
9503 * Return from the translation cache and immediately request
9504 * a translation for the exit target.  Commonly used following
9505 * invokes.
9506 */
9507    .global dvmJitToInterpTraceSelect
9508dvmJitToInterpTraceSelect:
9509    ldr    rPC,[lr, #-1]           @ get our target PC
9510    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9511    add    rINST,lr,#-5            @ save start of chain branch
9512    add    rINST, #-4              @  .. which is 9 bytes back
9513    mov    r0,rPC
9514    bl     dvmJitGetCodeAddr       @ Is there a translation?
9515    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9516    cmp    r0,#0
9517    beq    2f
9518    mov    r1,rINST
9519    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9520    mov    r1, rPC                  @ arg1 of translation may need this
9521    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9522    cmp    r0,#0                    @ successful chain?
9523    bxne   r0                       @ continue native execution
9524    b      toInterpreter            @ didn't chain - resume with interpreter
9525
9526/* No translation, so request one if profiling isn't disabled*/
95272:
9528    adrl   rIBASE, dvmAsmInstructionStart
9529    GET_JIT_PROF_TABLE(r0)
9530    FETCH_INST()
9531    cmp    r0, #0
9532    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9533    bne    common_selectTrace
9534    GET_INST_OPCODE(ip)
9535    GOTO_OPCODE(ip)
9536
9537/*
9538 * Return from the translation cache to the interpreter.
9539 * The return was done with a BLX from thumb mode, and
9540 * the following 32-bit word contains the target rPC value.
9541 * Note that lr (r14) will have its low-order bit set to denote
9542 * its thumb-mode origin.
9543 *
9544 * We'll need to stash our lr origin away, recover the new
9545 * target and then check to see if there is a translation available
9546 * for our new target.  If so, we do a translation chain and
9547 * go back to native execution.  Otherwise, it's back to the
9548 * interpreter (after treating this entry as a potential
9549 * trace start).
9550 */
9551    .global dvmJitToInterpNormal
9552dvmJitToInterpNormal:
9553    ldr    rPC,[lr, #-1]           @ get our target PC
9554    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9555    add    rINST,lr,#-5            @ save start of chain branch
9556    add    rINST,#-4               @ .. which is 9 bytes back
9557#if defined(WITH_JIT_TUNING)
9558    bl     dvmBumpNormal
9559#endif
9560    mov    r0,rPC
9561    bl     dvmJitGetCodeAddr        @ Is there a translation?
9562    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9563    cmp    r0,#0
9564    beq    toInterpreter            @ go if not, otherwise do chain
9565    mov    r1,rINST
9566    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9567    mov    r1, rPC                  @ arg1 of translation may need this
9568    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9569    cmp    r0,#0                    @ successful chain?
9570    bxne   r0                       @ continue native execution
9571    b      toInterpreter            @ didn't chain - resume with interpreter
9572
9573/*
9574 * Return from the translation cache to the interpreter to do method invocation.
9575 * Check if translation exists for the callee, but don't chain to it.
9576 */
9577    .global dvmJitToInterpNoChainNoProfile
9578dvmJitToInterpNoChainNoProfile:
9579#if defined(WITH_JIT_TUNING)
9580    bl     dvmBumpNoChain
9581#endif
9582    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9583    mov    r0,rPC
9584    bl     dvmJitGetCodeAddr        @ Is there a translation?
9585    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9586    mov    r1, rPC                  @ arg1 of translation may need this
9587    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9588    cmp    r0,#0
9589    bxne   r0                       @ continue native execution if so
9590    EXPORT_PC()
9591    adrl   rIBASE, dvmAsmInstructionStart
9592    FETCH_INST()
9593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9594    GOTO_OPCODE(ip)                     @ jump to next instruction
9595
9596/*
9597 * Return from the translation cache to the interpreter to do method invocation.
9598 * Check if translation exists for the callee, but don't chain to it.
9599 */
9600    .global dvmJitToInterpNoChain
9601dvmJitToInterpNoChain:
9602#if defined(WITH_JIT_TUNING)
9603    bl     dvmBumpNoChain
9604#endif
9605    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9606    mov    r0,rPC
9607    bl     dvmJitGetCodeAddr        @ Is there a translation?
9608    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9609    mov    r1, rPC                  @ arg1 of translation may need this
9610    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9611    cmp    r0,#0
9612    bxne   r0                       @ continue native execution if so
9613#endif
9614
9615/*
9616 * No translation, restore interpreter regs and start interpreting.
9617 * rGLUE & rFP were preserved in the translated code, and rPC has
9618 * already been restored by the time we get here.  We'll need to set
9619 * up rIBASE & rINST, and load the address of the JitTable into r0.
9620 */
9621toInterpreter:
9622    EXPORT_PC()
9623    adrl   rIBASE, dvmAsmInstructionStart
9624    FETCH_INST()
9625    GET_JIT_PROF_TABLE(r0)
9626    @ NOTE: intended fallthrough
9627
9628/*
9629 * Common code to update potential trace start counter, and initiate
9630 * a trace-build if appropriate.  On entry, rPC should point to the
9631 * next instruction to execute, and rINST should be already loaded with
9632 * the next opcode word, and r0 holds a pointer to the jit profile
9633 * table (pJitProfTable).
9634 */
9635common_testUpdateProfile:
9636    cmp     r0,#0
9637    GET_INST_OPCODE(ip)
9638    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9639
9640common_updateProfile:
9641    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9642    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9643    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9644    GET_INST_OPCODE(ip)
9645    subs    r1,r1,#1           @ decrement counter
9646    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9647    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9648
9649/*
9650 * Here, we switch to the debug interpreter to request
9651 * trace selection.  First, though, check to see if there
9652 * is already a native translation in place (and, if so,
9653 * jump to it now).
9654 */
9655    GET_JIT_THRESHOLD(r1)
9656    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9657    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9658    EXPORT_PC()
9659    mov     r0,rPC
9660    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9661    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9662    mov     r1, rPC                     @ arg1 of translation may need this
9663    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9664    cmp     r0,#0
9665#if !defined(WITH_SELF_VERIFICATION)
9666    bxne    r0                          @ jump to the translation
9667    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9668    @ fall-through to common_selectTrace
9669#else
9670    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9671    beq     common_selectTrace
9672    /*
9673     * At this point, we have a target translation.  However, if
9674     * that translation is actually the interpret-only pseudo-translation
9675     * we want to treat it the same as no translation.
9676     */
9677    mov     r10, r0                     @ save target
9678    bl      dvmCompilerGetInterpretTemplate
9679    cmp     r0, r10                     @ special case?
9680    bne     jitSVShadowRunStart         @ set up self verification shadow space
9681    @ Need to clear the inJitCodeCache flag
9682    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
9683    mov    r3, #0                       @ 0 means not in the JIT code cache
9684    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9685    GET_INST_OPCODE(ip)
9686    GOTO_OPCODE(ip)
9687    /* no return */
9688#endif
9689
9690/*
9691 * On entry:
9692 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9693 */
9694common_selectTrace:
9695    str     r2,[rGLUE,#offGlue_jitState]
9696    mov     r2,#kInterpEntryInstr       @ normal entry reason
9697    str     r2,[rGLUE,#offGlue_entryPoint]
9698    mov     r1,#1                       @ set changeInterp
9699    b       common_gotoBail
9700
9701#if defined(WITH_SELF_VERIFICATION)
9702/*
9703 * Save PC and registers to shadow memory for self verification mode
9704 * before jumping to native translation.
9705 * On entry:
9706 *    rPC, rFP, rGLUE: the values that they should contain
9707 *    r10: the address of the target translation.
9708 */
9709jitSVShadowRunStart:
9710    mov     r0,rPC                      @ r0<- program counter
9711    mov     r1,rFP                      @ r1<- frame pointer
9712    mov     r2,rGLUE                    @ r2<- InterpState pointer
9713    mov     r3,r10                      @ r3<- target translation
9714    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9715    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9716    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9717    bx      r10                         @ jump to the translation
9718
9719/*
9720 * Restore PC, registers, and interpState to original values
9721 * before jumping back to the interpreter.
9722 */
9723jitSVShadowRunEnd:
9724    mov    r1,rFP                        @ pass ending fp
9725    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9726    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9727    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9728    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9729    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9730    cmp    r1,#0                         @ check for punt condition
9731    beq    1f
9732    mov    r2,#kJitSelfVerification      @ ask for self verification
9733    str    r2,[rGLUE,#offGlue_jitState]
9734    mov    r2,#kInterpEntryInstr         @ normal entry reason
9735    str    r2,[rGLUE,#offGlue_entryPoint]
9736    mov    r1,#1                         @ set changeInterp
9737    b      common_gotoBail
9738
97391:                                       @ exit to interpreter without check
9740    EXPORT_PC()
9741    adrl   rIBASE, dvmAsmInstructionStart
9742    FETCH_INST()
9743    GET_INST_OPCODE(ip)
9744    GOTO_OPCODE(ip)
9745#endif
9746
9747#endif
9748
9749/*
9750 * Common code when a backward branch is taken.
9751 *
9752 * TODO: we could avoid a branch by just setting r0 and falling through
9753 * into the common_periodicChecks code, and having a test on r0 at the
9754 * end determine if we should return to the caller or update & branch to
9755 * the next instr.
9756 *
9757 * On entry:
9758 *  r9 is PC adjustment *in bytes*
9759 */
9760common_backwardBranch:
9761    mov     r0, #kInterpEntryInstr
9762    bl      common_periodicChecks
9763#if defined(WITH_JIT)
9764    GET_JIT_PROF_TABLE(r0)
9765    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9766    cmp     r0,#0
9767    bne     common_updateProfile
9768    GET_INST_OPCODE(ip)
9769    GOTO_OPCODE(ip)
9770#else
9771    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9772    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9773    GOTO_OPCODE(ip)                     @ jump to next instruction
9774#endif
9775
9776
9777/*
9778 * Need to see if the thread needs to be suspended or debugger/profiler
9779 * activity has begun.  If so, we suspend the thread or side-exit to
9780 * the debug interpreter as appropriate.
9781 *
9782 * The common case is no activity on any of these, so we want to figure
9783 * that out quickly.  If something is up, we can then sort out what.
9784 *
9785 * We want to be fast if the VM was built without debugger or profiler
9786 * support, but we also need to recognize that the system is usually
9787 * shipped with both of these enabled.
9788 *
9789 * TODO: reduce this so we're just checking a single location.
9790 *
9791 * On entry:
9792 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9793 *  r9 is trampoline PC adjustment *in bytes*
9794 */
9795common_periodicChecks:
9796    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9797
9798    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9799    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9800
9801    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9802
9803    cmp     r1, #0                      @ debugger enabled?
9804#if defined(WORKAROUND_CORTEX_A9_745320)
9805    /* Don't use conditional loads if the HW defect exists */
9806    beq     101f
9807    ldrb    r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9808101:
9809#else
9810    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9811#endif
9812    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9813    orrnes  ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9814    /*
9815     * Don't switch the interpreter in the libdvm_traceview build even if the
9816     * profiler is active.
9817     * The code here is opted for less intrusion instead of performance.
9818     * That is, *pActiveProfilers is still loaded into r2 even though it is not
9819     * used when WITH_INLINE_PROFILING is defined.
9820     */
9821#if !defined(WITH_INLINE_PROFILING)
9822    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9823#endif
9824
9825
9826    bxeq    lr                          @ all zero, return
9827
9828    /*
9829     * One or more interesting events have happened.  Figure out what.
9830     *
9831     * If debugging or profiling are compiled in, we need to disambiguate.
9832     *
9833     * r0 still holds the reentry type.
9834     */
9835    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9836    cmp     ip, #0                      @ want suspend?
9837    beq     1f                          @ no, must be debugger/profiler
9838
9839    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9840#if defined(WITH_JIT)
9841    /*
9842     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9843     * doubles as the Jit's on/off switch.
9844     */
9845    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9846    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9847    ldr     r3, [r3] @ r3 <- pJitProfTable
9848    EXPORT_PC()                         @ need for precise GC
9849    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9850#else
9851    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9852    EXPORT_PC()                         @ need for precise GC
9853#endif
9854    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9855    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9856
9857    /*
9858     * Reload the debugger/profiler enable flags.  We're checking to see
9859     * if either of these got set while we were suspended.
9860     *
9861     * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9862     * is enabled or not as the profiling will be done inline.
9863     */
9864    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9865    cmp     r1, #0                      @ debugger enabled?
9866#if defined(WORKAROUND_CORTEX_A9_745320)
9867    /* Don't use conditional loads if the HW defect exists */
9868    beq     101f
9869    ldrb    r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9870101:
9871#else
9872    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9873#endif
9874
9875#if !defined(WITH_INLINE_PROFILING)
9876    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9877    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9878    orrs    r1, r1, r2
9879#else
9880    cmp     r1, #0                      @ only consult the debuggerActive flag
9881#endif
9882
9883    beq     2f
9884
98851:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9886    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9887    add     rPC, rPC, r9                @ update rPC
9888    mov     r1, #1                      @ "want switch" = true
9889    b       common_gotoBail             @ side exit
9890
98912:
9892    bx      lr                          @ nothing to do, return
9893
9894
9895/*
9896 * The equivalent of "goto bail", this calls through the "bail handler".
9897 *
9898 * State registers will be saved to the "glue" area before bailing.
9899 *
9900 * On entry:
9901 *  r1 is "bool changeInterp", indicating if we want to switch to the
9902 *     other interpreter or just bail all the way out
9903 */
9904common_gotoBail:
9905    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9906    mov     r0, rGLUE                   @ r0<- glue ptr
9907    b       dvmMterpStdBail             @ call(glue, changeInterp)
9908
9909    @add     r1, r1, #1                  @ using (boolean+1)
9910    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9911    @bl      _longjmp                    @ does not return
9912    @bl      common_abort
9913
9914
9915/*
9916 * Common code for method invocation with range.
9917 *
9918 * On entry:
9919 *  r0 is "Method* methodToCall", the method we're trying to call
9920 */
9921common_invokeMethodRange:
9922.LinvokeNewRange:
9923    @ prepare to copy args to "outs" area of current frame
9924    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9925    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9926    beq     .LinvokeArgsDone            @ if no args, skip the rest
9927    FETCH(r1, 2)                        @ r1<- CCCC
9928
9929    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9930    @ (very few methods have > 10 args; could unroll for common cases)
9931    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9932    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9933    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
99341:  ldr     r1, [r3], #4                @ val = *fp++
9935    subs    r2, r2, #1                  @ count--
9936    str     r1, [r10], #4               @ *outs++ = val
9937    bne     1b                          @ ...while count != 0
9938    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9939    b       .LinvokeArgsDone
9940
9941/*
9942 * Common code for method invocation without range.
9943 *
9944 * On entry:
9945 *  r0 is "Method* methodToCall", the method we're trying to call
9946 */
9947common_invokeMethodNoRange:
9948.LinvokeNewNoRange:
9949    @ prepare to copy args to "outs" area of current frame
9950    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9951    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9952    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9953    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9954    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9955    beq     .LinvokeArgsDone
9956
9957    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9958.LinvokeNonRange:
9959    rsb     r2, r2, #5                  @ r2<- 5-r2
9960    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9961    bl      common_abort                @ (skipped due to ARM prefetch)
99625:  and     ip, rINST, #0x0f00          @ isolate A
9963    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9964    mov     r0, r0                      @ nop
9965    str     r2, [r10, #-4]!             @ *--outs = vA
99664:  and     ip, r1, #0xf000             @ isolate G
9967    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9968    mov     r0, r0                      @ nop
9969    str     r2, [r10, #-4]!             @ *--outs = vG
99703:  and     ip, r1, #0x0f00             @ isolate F
9971    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9972    mov     r0, r0                      @ nop
9973    str     r2, [r10, #-4]!             @ *--outs = vF
99742:  and     ip, r1, #0x00f0             @ isolate E
9975    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9976    mov     r0, r0                      @ nop
9977    str     r2, [r10, #-4]!             @ *--outs = vE
99781:  and     ip, r1, #0x000f             @ isolate D
9979    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9980    mov     r0, r0                      @ nop
9981    str     r2, [r10, #-4]!             @ *--outs = vD
99820:  @ fall through to .LinvokeArgsDone
9983
9984.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9985    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9986    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9987    @ find space for the new stack frame, check for overflow
9988    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9989    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9990    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9991@    bl      common_dumpRegs
9992    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9993    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9994    cmp     r3, r9                      @ bottom < interpStackEnd?
9995    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9996    blo     .LstackOverflow             @ yes, this frame will overflow stack
9997
9998    @ set up newSaveArea
9999#ifdef EASY_GDB
10000    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
10001    str     ip, [r10, #offStackSaveArea_prevSave]
10002#endif
10003    str     rFP, [r10, #offStackSaveArea_prevFrame]
10004    str     rPC, [r10, #offStackSaveArea_savedPc]
10005#if defined(WITH_JIT)
10006    mov     r9, #0
10007    str     r9, [r10, #offStackSaveArea_returnAddr]
10008#endif
10009#if defined(WITH_INLINE_PROFILING)
10010    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10011    mov     r1, r6
10012    @ r0=methodToCall, r1=rGlue
10013    bl      dvmFastMethodTraceEnter
10014    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10015#endif
10016    str     r0, [r10, #offStackSaveArea_method]
10017    tst     r3, #ACC_NATIVE
10018    bne     .LinvokeNative
10019
10020    /*
10021    stmfd   sp!, {r0-r3}
10022    bl      common_printNewline
10023    mov     r0, rFP
10024    mov     r1, #0
10025    bl      dvmDumpFp
10026    ldmfd   sp!, {r0-r3}
10027    stmfd   sp!, {r0-r3}
10028    mov     r0, r1
10029    mov     r1, r10
10030    bl      dvmDumpFp
10031    bl      common_printNewline
10032    ldmfd   sp!, {r0-r3}
10033    */
10034
10035    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10036    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10037    mov     rPC, r2                         @ publish new rPC
10038    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10039
10040    @ Update "glue" values for the new method
10041    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10042    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10043    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10044#if defined(WITH_JIT)
10045    GET_JIT_PROF_TABLE(r0)
10046    mov     rFP, r1                         @ fp = newFp
10047    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10048    mov     rINST, r9                       @ publish new rINST
10049    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10050    cmp     r0,#0
10051    bne     common_updateProfile
10052    GOTO_OPCODE(ip)                         @ jump to next instruction
10053#else
10054    mov     rFP, r1                         @ fp = newFp
10055    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10056    mov     rINST, r9                       @ publish new rINST
10057    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10058    GOTO_OPCODE(ip)                         @ jump to next instruction
10059#endif
10060
10061.LinvokeNative:
10062    @ Prep for the native call
10063    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10064    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10065    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10066    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10067    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10068    mov     r9, r3                      @ r9<- glue->self (preserve)
10069
10070    mov     r2, r0                      @ r2<- methodToCall
10071    mov     r0, r1                      @ r0<- newFp (points to args)
10072    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10073
10074#ifdef ASSIST_DEBUGGER
10075    /* insert fake function header to help gdb find the stack frame */
10076    b       .Lskip
10077    .type   dalvik_mterp, %function
10078dalvik_mterp:
10079    .fnstart
10080    MTERP_ENTRY1
10081    MTERP_ENTRY2
10082.Lskip:
10083#endif
10084
10085#if defined(WITH_INLINE_PROFILING)
10086    @ r2=JNIMethod, r6=rGLUE
10087    stmfd   sp!, {r2,r6}
10088#endif
10089
10090    mov     lr, pc                      @ set return addr
10091    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10092
10093#if defined(WITH_INLINE_PROFILING)
10094    @ r0=JNIMethod, r1=rGLUE
10095    ldmfd   sp!, {r0-r1}
10096    bl      dvmFastNativeMethodTraceExit
10097#endif
10098
10099#if defined(WITH_JIT)
10100    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10101#endif
10102
10103    @ native return; r9=self, r10=newSaveArea
10104    @ equivalent to dvmPopJniLocals
10105    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10106    ldr     r1, [r9, #offThread_exception] @ check for exception
10107#if defined(WITH_JIT)
10108    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10109#endif
10110    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10111    cmp     r1, #0                      @ null?
10112    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10113#if defined(WITH_JIT)
10114    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10115#endif
10116    bne     common_exceptionThrown      @ no, handle exception
10117
10118    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10119    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10120    GOTO_OPCODE(ip)                     @ jump to next instruction
10121
10122.LstackOverflow:    @ r0=methodToCall
10123    mov     r1, r0                      @ r1<- methodToCall
10124    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10125    bl      dvmHandleStackOverflow
10126    b       common_exceptionThrown
10127#ifdef ASSIST_DEBUGGER
10128    .fnend
10129#endif
10130
10131
10132    /*
10133     * Common code for method invocation, calling through "glue code".
10134     *
10135     * TODO: now that we have range and non-range invoke handlers, this
10136     *       needs to be split into two.  Maybe just create entry points
10137     *       that set r9 and jump here?
10138     *
10139     * On entry:
10140     *  r0 is "Method* methodToCall", the method we're trying to call
10141     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10142     */
10143     .if    0
10144.LinvokeOld:
10145    sub     sp, sp, #8                  @ space for args + pad
10146    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10147    mov     r2, r0                      @ A2<- methodToCall
10148    mov     r0, rGLUE                   @ A0<- glue
10149    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10150    mov     r1, r9                      @ A1<- methodCallRange
10151    mov     r3, rINST, lsr #8           @ A3<- AA
10152    str     ip, [sp, #0]                @ A4<- ip
10153    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10154    add     sp, sp, #8                  @ remove arg area
10155    b       common_resumeAfterGlueCall  @ continue to next instruction
10156    .endif
10157
10158
10159
10160/*
10161 * Common code for handling a return instruction.
10162 *
10163 * This does not return.
10164 */
10165common_returnFromMethod:
10166.LreturnNew:
10167    mov     r0, #kInterpEntryReturn
10168    mov     r9, #0
10169    bl      common_periodicChecks
10170
10171#if defined(WITH_INLINE_PROFILING)
10172    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10173    mov     r0, r6
10174    @ r0=rGlue
10175    bl      dvmFastJavaMethodTraceExit
10176    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10177#endif
10178    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10179    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10180    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10181    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10182                                        @ r2<- method we're returning to
10183    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10184    cmp     r2, #0                      @ is this a break frame?
10185#if defined(WORKAROUND_CORTEX_A9_745320)
10186    /* Don't use conditional loads if the HW defect exists */
10187    beq     101f
10188    ldr     r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10189101:
10190#else
10191    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10192#endif
10193    mov     r1, #0                      @ "want switch" = false
10194    beq     common_gotoBail             @ break frame, bail out completely
10195
10196    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10197    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10198    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10199    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10200#if defined(WITH_JIT)
10201    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10202    mov     rPC, r9                     @ publish new rPC
10203    str     r1, [rGLUE, #offGlue_methodClassDex]
10204    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10205    cmp     r10, #0                      @ caller is compiled code
10206    blxne   r10
10207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10208    GOTO_OPCODE(ip)                     @ jump to next instruction
10209#else
10210    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10211    mov     rPC, r9                     @ publish new rPC
10212    str     r1, [rGLUE, #offGlue_methodClassDex]
10213    GOTO_OPCODE(ip)                     @ jump to next instruction
10214#endif
10215
10216    /*
10217     * Return handling, calls through "glue code".
10218     */
10219     .if    0
10220.LreturnOld:
10221    SAVE_PC_FP_TO_GLUE()                @ export state
10222    mov     r0, rGLUE                   @ arg to function
10223    bl      dvmMterp_returnFromMethod
10224    b       common_resumeAfterGlueCall
10225    .endif
10226
10227
10228/*
10229 * Somebody has thrown an exception.  Handle it.
10230 *
10231 * If the exception processing code returns to us (instead of falling
10232 * out of the interpreter), continue with whatever the next instruction
10233 * now happens to be.
10234 *
10235 * This does not return.
10236 */
10237     .global dvmMterpCommonExceptionThrown
10238dvmMterpCommonExceptionThrown:
10239common_exceptionThrown:
10240.LexceptionNew:
10241    mov     r0, #kInterpEntryThrow
10242    mov     r9, #0
10243    bl      common_periodicChecks
10244
10245    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10246    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10247    mov     r1, r10                     @ r1<- self
10248    mov     r0, r9                      @ r0<- exception
10249    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10250    mov     r3, #0                      @ r3<- NULL
10251    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10252
10253    /* set up args and a local for "&fp" */
10254    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10255    str     rFP, [sp, #-4]!             @ *--sp = fp
10256    mov     ip, sp                      @ ip<- &fp
10257    mov     r3, #0                      @ r3<- false
10258    str     ip, [sp, #-4]!              @ *--sp = &fp
10259    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10260    mov     r0, r10                     @ r0<- self
10261    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10262    mov     r2, r9                      @ r2<- exception
10263    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10264    mov     r1, r1, asr #1              @ r1<- offset in code units
10265
10266    /* call, r0 gets catchRelPc (a code-unit offset) */
10267    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10268
10269    /* fix earlier stack overflow if necessary; may trash rFP */
10270    ldrb    r1, [r10, #offThread_stackOverflowed]
10271    cmp     r1, #0                      @ did we overflow earlier?
10272    beq     1f                          @ no, skip ahead
10273    mov     rFP, r0                     @ save relPc result in rFP
10274    mov     r0, r10                     @ r0<- self
10275    mov     r1, r9                      @ r1<- exception
10276    bl      dvmCleanupStackOverflow     @ call(self)
10277    mov     r0, rFP                     @ restore result
102781:
10279
10280    /* update frame pointer and check result from dvmFindCatchBlock */
10281    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10282    cmp     r0, #0                      @ is catchRelPc < 0?
10283    add     sp, sp, #8                  @ restore stack
10284    bmi     .LnotCaughtLocally
10285
10286    /* adjust locals to match self->curFrame and updated PC */
10287    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10288    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10289    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10290    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10291    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10292    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10293    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10294    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10295
10296    /* release the tracked alloc on the exception */
10297    mov     r0, r9                      @ r0<- exception
10298    mov     r1, r10                     @ r1<- self
10299    bl      dvmReleaseTrackedAlloc      @ release the exception
10300
10301    /* restore the exception if the handler wants it */
10302    FETCH_INST()                        @ load rINST from rPC
10303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10304    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10305    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10306    GOTO_OPCODE(ip)                     @ jump to next instruction
10307
10308.LnotCaughtLocally: @ r9=exception, r10=self
10309    /* fix stack overflow if necessary */
10310    ldrb    r1, [r10, #offThread_stackOverflowed]
10311    cmp     r1, #0                      @ did we overflow earlier?
10312    movne   r0, r10                     @ if yes: r0<- self
10313    movne   r1, r9                      @ if yes: r1<- exception
10314    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10315
10316    @ may want to show "not caught locally" debug messages here
10317#if DVM_SHOW_EXCEPTION >= 2
10318    /* call __android_log_print(prio, tag, format, ...) */
10319    /* "Exception %s from %s:%d not caught locally" */
10320    @ dvmLineNumFromPC(method, pc - method->insns)
10321    ldr     r0, [rGLUE, #offGlue_method]
10322    ldr     r1, [r0, #offMethod_insns]
10323    sub     r1, rPC, r1
10324    asr     r1, r1, #1
10325    bl      dvmLineNumFromPC
10326    str     r0, [sp, #-4]!
10327    @ dvmGetMethodSourceFile(method)
10328    ldr     r0, [rGLUE, #offGlue_method]
10329    bl      dvmGetMethodSourceFile
10330    str     r0, [sp, #-4]!
10331    @ exception->clazz->descriptor
10332    ldr     r3, [r9, #offObject_clazz]
10333    ldr     r3, [r3, #offClassObject_descriptor]
10334    @
10335    ldr     r2, strExceptionNotCaughtLocally
10336    ldr     r1, strLogTag
10337    mov     r0, #3                      @ LOG_DEBUG
10338    bl      __android_log_print
10339#endif
10340    str     r9, [r10, #offThread_exception] @ restore exception
10341    mov     r0, r9                      @ r0<- exception
10342    mov     r1, r10                     @ r1<- self
10343    bl      dvmReleaseTrackedAlloc      @ release the exception
10344    mov     r1, #0                      @ "want switch" = false
10345    b       common_gotoBail             @ bail out
10346
10347
10348    /*
10349     * Exception handling, calls through "glue code".
10350     */
10351    .if     0
10352.LexceptionOld:
10353    SAVE_PC_FP_TO_GLUE()                @ export state
10354    mov     r0, rGLUE                   @ arg to function
10355    bl      dvmMterp_exceptionThrown
10356    b       common_resumeAfterGlueCall
10357    .endif
10358
10359
10360/*
10361 * After returning from a "glued" function, pull out the updated
10362 * values and start executing at the next instruction.
10363 */
10364common_resumeAfterGlueCall:
10365    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10366    FETCH_INST()                        @ load rINST from rPC
10367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10368    GOTO_OPCODE(ip)                     @ jump to next instruction
10369
10370/*
10371 * Invalid array index. Note that our calling convention is strange; we use r1
10372 * and r3 because those just happen to be the registers all our callers are
10373 * using. We shuffle them here before calling the C function.
10374 * r1: index
10375 * r3: size
10376 */
10377common_errArrayIndex:
10378    EXPORT_PC()
10379    mov     r0, r1
10380    mov     r1, r3
10381    bl      dvmThrowAIOOBE
10382    b       common_exceptionThrown
10383
10384/*
10385 * Invalid array value.
10386 */
10387common_errArrayStore:
10388    EXPORT_PC()
10389    ldr     r0, strArrayStoreException
10390    mov     r1, #0
10391    bl      dvmThrowException
10392    b       common_exceptionThrown
10393
10394/*
10395 * Integer divide or mod by zero.
10396 */
10397common_errDivideByZero:
10398    EXPORT_PC()
10399    ldr     r0, strArithmeticException
10400    ldr     r1, strDivideByZero
10401    bl      dvmThrowException
10402    b       common_exceptionThrown
10403
10404/*
10405 * Attempt to allocate an array with a negative size.
10406 */
10407common_errNegativeArraySize:
10408    EXPORT_PC()
10409    ldr     r0, strNegativeArraySizeException
10410    mov     r1, #0
10411    bl      dvmThrowException
10412    b       common_exceptionThrown
10413
10414/*
10415 * Invocation of a non-existent method.
10416 */
10417common_errNoSuchMethod:
10418    EXPORT_PC()
10419    ldr     r0, strNoSuchMethodError
10420    mov     r1, #0
10421    bl      dvmThrowException
10422    b       common_exceptionThrown
10423
10424/*
10425 * We encountered a null object when we weren't expecting one.  We
10426 * export the PC, throw a NullPointerException, and goto the exception
10427 * processing code.
10428 */
10429common_errNullObject:
10430    EXPORT_PC()
10431    ldr     r0, strNullPointerException
10432    mov     r1, #0
10433    bl      dvmThrowException
10434    b       common_exceptionThrown
10435
10436/*
10437 * For debugging, cause an immediate fault.  The source address will
10438 * be in lr (use a bl instruction to jump here).
10439 */
10440common_abort:
10441    ldr     pc, .LdeadFood
10442.LdeadFood:
10443    .word   0xdeadf00d
10444
10445/*
10446 * Spit out a "we were here", preserving all registers.  (The attempt
10447 * to save ip won't work, but we need to save an even number of
10448 * registers for EABI 64-bit stack alignment.)
10449 */
10450    .macro  SQUEAK num
10451common_squeak\num:
10452    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10453    ldr     r0, strSqueak
10454    mov     r1, #\num
10455    bl      printf
10456    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10457    bx      lr
10458    .endm
10459
10460    SQUEAK  0
10461    SQUEAK  1
10462    SQUEAK  2
10463    SQUEAK  3
10464    SQUEAK  4
10465    SQUEAK  5
10466
10467/*
10468 * Spit out the number in r0, preserving registers.
10469 */
10470common_printNum:
10471    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10472    mov     r1, r0
10473    ldr     r0, strSqueak
10474    bl      printf
10475    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10476    bx      lr
10477
10478/*
10479 * Print a newline, preserving registers.
10480 */
10481common_printNewline:
10482    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10483    ldr     r0, strNewline
10484    bl      printf
10485    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10486    bx      lr
10487
10488    /*
10489     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10490     */
10491common_printHex:
10492    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10493    mov     r1, r0
10494    ldr     r0, strPrintHex
10495    bl      printf
10496    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10497    bx      lr
10498
10499/*
10500 * Print the 64-bit quantity in r0-r1, preserving registers.
10501 */
10502common_printLong:
10503    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10504    mov     r3, r1
10505    mov     r2, r0
10506    ldr     r0, strPrintLong
10507    bl      printf
10508    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10509    bx      lr
10510
10511/*
10512 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10513 */
10514common_printMethod:
10515    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10516    bl      dvmMterpPrintMethod
10517    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10518    bx      lr
10519
10520/*
10521 * Call a C helper function that dumps regs and possibly some
10522 * additional info.  Requires the C function to be compiled in.
10523 */
10524    .if     0
10525common_dumpRegs:
10526    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10527    bl      dvmMterpDumpArmRegs
10528    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10529    bx      lr
10530    .endif
10531
10532#if 0
10533/*
10534 * Experiment on VFP mode.
10535 *
10536 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10537 *
10538 * Updates the bits specified by "mask", setting them to the values in "val".
10539 */
10540setFPSCR:
10541    and     r0, r0, r1                  @ make sure no stray bits are set
10542    fmrx    r2, fpscr                   @ get VFP reg
10543    mvn     r1, r1                      @ bit-invert mask
10544    and     r2, r2, r1                  @ clear masked bits
10545    orr     r2, r2, r0                  @ set specified bits
10546    fmxr    fpscr, r2                   @ set VFP reg
10547    mov     r0, r2                      @ return new value
10548    bx      lr
10549
10550    .align  2
10551    .global dvmConfigureFP
10552    .type   dvmConfigureFP, %function
10553dvmConfigureFP:
10554    stmfd   sp!, {ip, lr}
10555    /* 0x03000000 sets DN/FZ */
10556    /* 0x00009f00 clears the six exception enable flags */
10557    bl      common_squeak0
10558    mov     r0, #0x03000000             @ r0<- 0x03000000
10559    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10560    bl      setFPSCR
10561    ldmfd   sp!, {ip, pc}
10562#endif
10563
10564
10565/*
10566 * String references, must be close to the code that uses them.
10567 */
10568    .align  2
10569strArithmeticException:
10570    .word   .LstrArithmeticException
10571strArrayStoreException:
10572    .word   .LstrArrayStoreException
10573strDivideByZero:
10574    .word   .LstrDivideByZero
10575strNegativeArraySizeException:
10576    .word   .LstrNegativeArraySizeException
10577strNoSuchMethodError:
10578    .word   .LstrNoSuchMethodError
10579strNullPointerException:
10580    .word   .LstrNullPointerException
10581
10582strLogTag:
10583    .word   .LstrLogTag
10584strExceptionNotCaughtLocally:
10585    .word   .LstrExceptionNotCaughtLocally
10586
10587strNewline:
10588    .word   .LstrNewline
10589strSqueak:
10590    .word   .LstrSqueak
10591strPrintHex:
10592    .word   .LstrPrintHex
10593strPrintLong:
10594    .word   .LstrPrintLong
10595
10596/*
10597 * Zero-terminated ASCII string data.
10598 *
10599 * On ARM we have two choices: do like gcc does, and LDR from a .word
10600 * with the address, or use an ADR pseudo-op to get the address
10601 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10602 * PC-relative addressing mode and hence has a limited range, which
10603 * makes it not work well with mergeable string sections.
10604 */
10605    .section .rodata.str1.4,"aMS",%progbits,1
10606
10607.LstrBadEntryPoint:
10608    .asciz  "Bad entry point %d\n"
10609.LstrArithmeticException:
10610    .asciz  "Ljava/lang/ArithmeticException;"
10611.LstrArrayStoreException:
10612    .asciz  "Ljava/lang/ArrayStoreException;"
10613.LstrDivideByZero:
10614    .asciz  "divide by zero"
10615.LstrFilledNewArrayNotImpl:
10616    .asciz  "filled-new-array only implemented for objects and 'int'"
10617.LstrInternalError:
10618    .asciz  "Ljava/lang/InternalError;"
10619.LstrInstantiationError:
10620    .asciz  "Ljava/lang/InstantiationError;"
10621.LstrNegativeArraySizeException:
10622    .asciz  "Ljava/lang/NegativeArraySizeException;"
10623.LstrNoSuchMethodError:
10624    .asciz  "Ljava/lang/NoSuchMethodError;"
10625.LstrNullPointerException:
10626    .asciz  "Ljava/lang/NullPointerException;"
10627
10628.LstrLogTag:
10629    .asciz  "mterp"
10630.LstrExceptionNotCaughtLocally:
10631    .asciz  "Exception %s from %s:%d not caught locally\n"
10632
10633.LstrNewline:
10634    .asciz  "\n"
10635.LstrSqueak:
10636    .asciz  "<%d>"
10637.LstrPrintHex:
10638    .asciz  "<0x%x>"
10639.LstrPrintLong:
10640    .asciz  "<%lld>"
10641
10642