InterpAsm-armv7-a.S revision 7a2697d327936e20ef5484f7819e2e4bf91c891f
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
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: armv7-a/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216/*
217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
218 * one-way branch.
219 *
220 * May modify IP.  Does not modify LR.
221 */
222.macro  LDR_PC source
223    ldr     pc, \source
224.endm
225
226/*
227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
228 * Jump to subroutine.
229 *
230 * May modify IP and LR.
231 */
232.macro  LDR_PC_LR source
233    mov     lr, pc
234    ldr     pc, \source
235.endm
236
237/*
238 * Macro for "LDMFD SP!, {...regs...,PC}".
239 *
240 * May modify IP and LR.
241 */
242.macro  LDMFD_PC regs
243    ldmfd   sp!, {\regs,pc}
244.endm
245
246#if !defined(ANDROID_SMP)
247# error "Must define ANDROID_SMP"
248#endif
249
250/*
251 * Macro for data memory barrier; not meaningful pre-ARMv6K.
252 * If the argument is nonzero, emit barrier; otherwise, emit nothing.
253 */
254.macro  SMP_DMB
255#if ANDROID_SMP != 0
256    dmb
257#else
258    /* not SMP */
259#endif
260.endm
261
262/* File: armv5te/entry.S */
263/*
264 * Copyright (C) 2008 The Android Open Source Project
265 *
266 * Licensed under the Apache License, Version 2.0 (the "License");
267 * you may not use this file except in compliance with the License.
268 * You may obtain a copy of the License at
269 *
270 *      http://www.apache.org/licenses/LICENSE-2.0
271 *
272 * Unless required by applicable law or agreed to in writing, software
273 * distributed under the License is distributed on an "AS IS" BASIS,
274 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
275 * See the License for the specific language governing permissions and
276 * limitations under the License.
277 */
278/*
279 * Interpreter entry point.
280 */
281
282/*
283 * We don't have formal stack frames, so gdb scans upward in the code
284 * to find the start of the function (a label with the %function type),
285 * and then looks at the next few instructions to figure out what
286 * got pushed onto the stack.  From this it figures out how to restore
287 * the registers, including PC, for the previous stack frame.  If gdb
288 * sees a non-function label, it stops scanning, so either we need to
289 * have nothing but assembler-local labels between the entry point and
290 * the break, or we need to fake it out.
291 *
292 * When this is defined, we add some stuff to make gdb less confused.
293 */
294#define ASSIST_DEBUGGER 1
295
296    .text
297    .align  2
298    .global dvmMterpStdRun
299    .type   dvmMterpStdRun, %function
300
301/*
302 * On entry:
303 *  r0  MterpGlue* glue
304 *
305 * This function returns a boolean "changeInterp" value.  The return comes
306 * via a call to dvmMterpStdBail().
307 */
308dvmMterpStdRun:
309#define MTERP_ENTRY1 \
310    .save {r4-r10,fp,lr}; \
311    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
312#define MTERP_ENTRY2 \
313    .pad    #4; \
314    sub     sp, sp, #4                  @ align 64
315
316    .fnstart
317    MTERP_ENTRY1
318    MTERP_ENTRY2
319
320    /* save stack pointer, add magic word for debuggerd */
321    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
322
323    /* set up "named" registers, figure out entry point */
324    mov     rGLUE, r0                   @ set rGLUE
325    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
326    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
327    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
328    cmp     r1, #kInterpEntryInstr      @ usual case?
329    bne     .Lnot_instr                 @ no, handle it
330
331#if defined(WITH_JIT)
332.LentryInstr:
333    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
334    /* Entry is always a possible trace start */
335    GET_JIT_PROF_TABLE(r0)
336    FETCH_INST()
337    mov     r1, #0                      @ prepare the value for the new state
338    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
339    cmp     r0,#0                       @ is profiling disabled?
340#if !defined(WITH_SELF_VERIFICATION)
341    bne     common_updateProfile        @ profiling is enabled
342#else
343    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
344    beq     1f                          @ profiling is disabled
345    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
346    cmp     r3, #kSVSTraceSelect        @ hot trace following?
347    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
348    beq     common_selectTrace          @ go build the trace
349    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
350    beq     1f                          @ intrepret the next instruction
351    b       common_updateProfile        @ collect profiles
352#endif
3531:
354    GET_INST_OPCODE(ip)
355    GOTO_OPCODE(ip)
356#else
357    /* start executing the instruction at rPC */
358    FETCH_INST()                        @ load rINST from rPC
359    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
360    GOTO_OPCODE(ip)                     @ jump to next instruction
361#endif
362
363.Lnot_instr:
364    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
365    beq     common_returnFromMethod
366
367.Lnot_return:
368    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
369    beq     common_exceptionThrown
370
371#if defined(WITH_JIT)
372.Lnot_throw:
373    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
374    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
375    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
376    bne     .Lbad_arg
377    cmp     rPC,r2
378    bne     .LentryInstr                @ must have branched, don't resume
379#if defined(WITH_SELF_VERIFICATION)
380    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
381    b       jitSVShadowRunStart         @ re-enter the translation after the
382                                        @ single-stepped instruction
383    @noreturn
384#endif
385    mov     r1, #kInterpEntryInstr
386    str     r1, [rGLUE, #offGlue_entryPoint]
387    bx      r10                         @ re-enter the translation
388#endif
389
390.Lbad_arg:
391    ldr     r0, strBadEntryPoint
392    @ r1 holds value of entryPoint
393    bl      printf
394    bl      dvmAbort
395    .fnend
396
397
398    .global dvmMterpStdBail
399    .type   dvmMterpStdBail, %function
400
401/*
402 * Restore the stack pointer and PC from the save point established on entry.
403 * This is essentially the same as a longjmp, but should be cheaper.  The
404 * last instruction causes us to return to whoever called dvmMterpStdRun.
405 *
406 * We pushed some registers on the stack in dvmMterpStdRun, then saved
407 * SP and LR.  Here we restore SP, restore the registers, and then restore
408 * LR to PC.
409 *
410 * On entry:
411 *  r0  MterpGlue* glue
412 *  r1  bool changeInterp
413 */
414dvmMterpStdBail:
415    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
416    mov     r0, r1                          @ return the changeInterp value
417    add     sp, sp, #4                      @ un-align 64
418    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
419
420
421/*
422 * String references.
423 */
424strBadEntryPoint:
425    .word   .LstrBadEntryPoint
426
427
428    .global dvmAsmInstructionStart
429    .type   dvmAsmInstructionStart, %function
430dvmAsmInstructionStart = .L_OP_NOP
431    .text
432
433/* ------------------------------ */
434    .balign 64
435.L_OP_NOP: /* 0x00 */
436/* File: armv5te/OP_NOP.S */
437    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
438    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
439    GOTO_OPCODE(ip)                     @ execute it
440
441#ifdef ASSIST_DEBUGGER
442    /* insert fake function header to help gdb find the stack frame */
443    .type   dalvik_inst, %function
444dalvik_inst:
445    .fnstart
446    MTERP_ENTRY1
447    MTERP_ENTRY2
448    .fnend
449#endif
450
451/* ------------------------------ */
452    .balign 64
453.L_OP_MOVE: /* 0x01 */
454/* File: armv6t2/OP_MOVE.S */
455    /* for move, move-object, long-to-int */
456    /* op vA, vB */
457    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
458    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
459    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
460    GET_VREG(r2, r1)                    @ r2<- fp[B]
461    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
462    SET_VREG(r2, r0)                    @ fp[A]<- r2
463    GOTO_OPCODE(ip)                     @ execute next instruction
464
465/* ------------------------------ */
466    .balign 64
467.L_OP_MOVE_FROM16: /* 0x02 */
468/* File: armv5te/OP_MOVE_FROM16.S */
469    /* for: move/from16, move-object/from16 */
470    /* op vAA, vBBBB */
471    FETCH(r1, 1)                        @ r1<- BBBB
472    mov     r0, rINST, lsr #8           @ r0<- AA
473    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
474    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
475    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
476    SET_VREG(r2, r0)                    @ fp[AA]<- r2
477    GOTO_OPCODE(ip)                     @ jump to next instruction
478
479/* ------------------------------ */
480    .balign 64
481.L_OP_MOVE_16: /* 0x03 */
482/* File: armv5te/OP_MOVE_16.S */
483    /* for: move/16, move-object/16 */
484    /* op vAAAA, vBBBB */
485    FETCH(r1, 2)                        @ r1<- BBBB
486    FETCH(r0, 1)                        @ r0<- AAAA
487    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
488    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
489    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
490    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
491    GOTO_OPCODE(ip)                     @ jump to next instruction
492
493/* ------------------------------ */
494    .balign 64
495.L_OP_MOVE_WIDE: /* 0x04 */
496/* File: armv6t2/OP_MOVE_WIDE.S */
497    /* move-wide vA, vB */
498    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
499    mov     r3, rINST, lsr #12          @ r3<- B
500    ubfx    r2, rINST, #8, #4           @ r2<- A
501    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
502    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
503    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
504    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
506    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
507    GOTO_OPCODE(ip)                     @ jump to next instruction
508
509/* ------------------------------ */
510    .balign 64
511.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
512/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
513    /* move-wide/from16 vAA, vBBBB */
514    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
515    FETCH(r3, 1)                        @ r3<- BBBB
516    mov     r2, rINST, lsr #8           @ r2<- AA
517    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
518    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
519    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
520    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
521    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
522    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
523    GOTO_OPCODE(ip)                     @ jump to next instruction
524
525/* ------------------------------ */
526    .balign 64
527.L_OP_MOVE_WIDE_16: /* 0x06 */
528/* File: armv5te/OP_MOVE_WIDE_16.S */
529    /* move-wide/16 vAAAA, vBBBB */
530    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
531    FETCH(r3, 2)                        @ r3<- BBBB
532    FETCH(r2, 1)                        @ r2<- AAAA
533    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
534    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
535    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
536    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
538    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
539    GOTO_OPCODE(ip)                     @ jump to next instruction
540
541/* ------------------------------ */
542    .balign 64
543.L_OP_MOVE_OBJECT: /* 0x07 */
544/* File: armv5te/OP_MOVE_OBJECT.S */
545/* File: armv5te/OP_MOVE.S */
546    /* for move, move-object, long-to-int */
547    /* op vA, vB */
548    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
549    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
550    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
551    GET_VREG(r2, r1)                    @ r2<- fp[B]
552    and     r0, r0, #15
553    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
554    SET_VREG(r2, r0)                    @ fp[A]<- r2
555    GOTO_OPCODE(ip)                     @ execute next instruction
556
557
558/* ------------------------------ */
559    .balign 64
560.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
561/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
562/* File: armv5te/OP_MOVE_FROM16.S */
563    /* for: move/from16, move-object/from16 */
564    /* op vAA, vBBBB */
565    FETCH(r1, 1)                        @ r1<- BBBB
566    mov     r0, rINST, lsr #8           @ r0<- AA
567    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
568    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
569    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
570    SET_VREG(r2, r0)                    @ fp[AA]<- r2
571    GOTO_OPCODE(ip)                     @ jump to next instruction
572
573
574/* ------------------------------ */
575    .balign 64
576.L_OP_MOVE_OBJECT_16: /* 0x09 */
577/* File: armv5te/OP_MOVE_OBJECT_16.S */
578/* File: armv5te/OP_MOVE_16.S */
579    /* for: move/16, move-object/16 */
580    /* op vAAAA, vBBBB */
581    FETCH(r1, 2)                        @ r1<- BBBB
582    FETCH(r0, 1)                        @ r0<- AAAA
583    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
584    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
585    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
586    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
587    GOTO_OPCODE(ip)                     @ jump to next instruction
588
589
590/* ------------------------------ */
591    .balign 64
592.L_OP_MOVE_RESULT: /* 0x0a */
593/* File: armv5te/OP_MOVE_RESULT.S */
594    /* for: move-result, move-result-object */
595    /* op vAA */
596    mov     r2, rINST, lsr #8           @ r2<- AA
597    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
598    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
599    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
600    SET_VREG(r0, r2)                    @ fp[AA]<- r0
601    GOTO_OPCODE(ip)                     @ jump to next instruction
602
603/* ------------------------------ */
604    .balign 64
605.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
606/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
607    /* move-result-wide vAA */
608    mov     r2, rINST, lsr #8           @ r2<- AA
609    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
610    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
611    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
612    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
614    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
615    GOTO_OPCODE(ip)                     @ jump to next instruction
616
617/* ------------------------------ */
618    .balign 64
619.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
620/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
621/* File: armv5te/OP_MOVE_RESULT.S */
622    /* for: move-result, move-result-object */
623    /* op vAA */
624    mov     r2, rINST, lsr #8           @ r2<- AA
625    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
626    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
627    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
628    SET_VREG(r0, r2)                    @ fp[AA]<- r0
629    GOTO_OPCODE(ip)                     @ jump to next instruction
630
631
632/* ------------------------------ */
633    .balign 64
634.L_OP_MOVE_EXCEPTION: /* 0x0d */
635/* File: armv5te/OP_MOVE_EXCEPTION.S */
636    /* move-exception vAA */
637    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
638    mov     r2, rINST, lsr #8           @ r2<- AA
639    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
640    mov     r1, #0                      @ r1<- 0
641    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
642    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
643    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
644    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
645    GOTO_OPCODE(ip)                     @ jump to next instruction
646
647/* ------------------------------ */
648    .balign 64
649.L_OP_RETURN_VOID: /* 0x0e */
650/* File: armv5te/OP_RETURN_VOID.S */
651    b       common_returnFromMethod
652
653/* ------------------------------ */
654    .balign 64
655.L_OP_RETURN: /* 0x0f */
656/* File: armv5te/OP_RETURN.S */
657    /*
658     * Return a 32-bit value.  Copies the return value into the "glue"
659     * structure, then jumps to the return handler.
660     *
661     * for: return, return-object
662     */
663    /* op vAA */
664    mov     r2, rINST, lsr #8           @ r2<- AA
665    GET_VREG(r0, r2)                    @ r0<- vAA
666    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
667    b       common_returnFromMethod
668
669/* ------------------------------ */
670    .balign 64
671.L_OP_RETURN_WIDE: /* 0x10 */
672/* File: armv5te/OP_RETURN_WIDE.S */
673    /*
674     * Return a 64-bit value.  Copies the return value into the "glue"
675     * structure, then jumps to the return handler.
676     */
677    /* return-wide vAA */
678    mov     r2, rINST, lsr #8           @ r2<- AA
679    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
680    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
681    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
682    stmia   r3, {r0-r1}                 @ retval<- r0/r1
683    b       common_returnFromMethod
684
685/* ------------------------------ */
686    .balign 64
687.L_OP_RETURN_OBJECT: /* 0x11 */
688/* File: armv5te/OP_RETURN_OBJECT.S */
689/* File: armv5te/OP_RETURN.S */
690    /*
691     * Return a 32-bit value.  Copies the return value into the "glue"
692     * structure, then jumps to the return handler.
693     *
694     * for: return, return-object
695     */
696    /* op vAA */
697    mov     r2, rINST, lsr #8           @ r2<- AA
698    GET_VREG(r0, r2)                    @ r0<- vAA
699    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
700    b       common_returnFromMethod
701
702
703/* ------------------------------ */
704    .balign 64
705.L_OP_CONST_4: /* 0x12 */
706/* File: armv6t2/OP_CONST_4.S */
707    /* const/4 vA, #+B */
708    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
709    ubfx    r0, rINST, #8, #4           @ r0<- A
710    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
711    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
712    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
713    SET_VREG(r1, r0)                    @ fp[A]<- r1
714    GOTO_OPCODE(ip)                     @ execute next instruction
715
716/* ------------------------------ */
717    .balign 64
718.L_OP_CONST_16: /* 0x13 */
719/* File: armv5te/OP_CONST_16.S */
720    /* const/16 vAA, #+BBBB */
721    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
722    mov     r3, rINST, lsr #8           @ r3<- AA
723    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
724    SET_VREG(r0, r3)                    @ vAA<- r0
725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
726    GOTO_OPCODE(ip)                     @ jump to next instruction
727
728/* ------------------------------ */
729    .balign 64
730.L_OP_CONST: /* 0x14 */
731/* File: armv5te/OP_CONST.S */
732    /* const vAA, #+BBBBbbbb */
733    mov     r3, rINST, lsr #8           @ r3<- AA
734    FETCH(r0, 1)                        @ r0<- bbbb (low)
735    FETCH(r1, 2)                        @ r1<- BBBB (high)
736    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
737    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
738    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
739    SET_VREG(r0, r3)                    @ vAA<- r0
740    GOTO_OPCODE(ip)                     @ jump to next instruction
741
742/* ------------------------------ */
743    .balign 64
744.L_OP_CONST_HIGH16: /* 0x15 */
745/* File: armv5te/OP_CONST_HIGH16.S */
746    /* const/high16 vAA, #+BBBB0000 */
747    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
748    mov     r3, rINST, lsr #8           @ r3<- AA
749    mov     r0, r0, lsl #16             @ r0<- BBBB0000
750    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
751    SET_VREG(r0, r3)                    @ vAA<- r0
752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
753    GOTO_OPCODE(ip)                     @ jump to next instruction
754
755/* ------------------------------ */
756    .balign 64
757.L_OP_CONST_WIDE_16: /* 0x16 */
758/* File: armv5te/OP_CONST_WIDE_16.S */
759    /* const-wide/16 vAA, #+BBBB */
760    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
761    mov     r3, rINST, lsr #8           @ r3<- AA
762    mov     r1, r0, asr #31             @ r1<- ssssssss
763    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
764    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
765    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
766    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
767    GOTO_OPCODE(ip)                     @ jump to next instruction
768
769/* ------------------------------ */
770    .balign 64
771.L_OP_CONST_WIDE_32: /* 0x17 */
772/* File: armv5te/OP_CONST_WIDE_32.S */
773    /* const-wide/32 vAA, #+BBBBbbbb */
774    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
775    mov     r3, rINST, lsr #8           @ r3<- AA
776    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
777    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
778    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
779    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
780    mov     r1, r0, asr #31             @ r1<- ssssssss
781    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
782    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
783    GOTO_OPCODE(ip)                     @ jump to next instruction
784
785/* ------------------------------ */
786    .balign 64
787.L_OP_CONST_WIDE: /* 0x18 */
788/* File: armv5te/OP_CONST_WIDE.S */
789    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
790    FETCH(r0, 1)                        @ r0<- bbbb (low)
791    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
792    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
793    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
794    FETCH(r3, 4)                        @ r3<- HHHH (high)
795    mov     r9, rINST, lsr #8           @ r9<- AA
796    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
797    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
798    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
800    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
801    GOTO_OPCODE(ip)                     @ jump to next instruction
802
803/* ------------------------------ */
804    .balign 64
805.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
806/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
807    /* const-wide/high16 vAA, #+BBBB000000000000 */
808    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
809    mov     r3, rINST, lsr #8           @ r3<- AA
810    mov     r0, #0                      @ r0<- 00000000
811    mov     r1, r1, lsl #16             @ r1<- BBBB0000
812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
813    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
814    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
815    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
816    GOTO_OPCODE(ip)                     @ jump to next instruction
817
818/* ------------------------------ */
819    .balign 64
820.L_OP_CONST_STRING: /* 0x1a */
821/* File: armv5te/OP_CONST_STRING.S */
822    /* const/string vAA, String@BBBB */
823    FETCH(r1, 1)                        @ r1<- BBBB
824    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
825    mov     r9, rINST, lsr #8           @ r9<- AA
826    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
827    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
828    cmp     r0, #0                      @ not yet resolved?
829    beq     .LOP_CONST_STRING_resolve
830    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
832    SET_VREG(r0, r9)                    @ vAA<- r0
833    GOTO_OPCODE(ip)                     @ jump to next instruction
834
835/* ------------------------------ */
836    .balign 64
837.L_OP_CONST_STRING_JUMBO: /* 0x1b */
838/* File: armv5te/OP_CONST_STRING_JUMBO.S */
839    /* const/string vAA, String@BBBBBBBB */
840    FETCH(r0, 1)                        @ r0<- bbbb (low)
841    FETCH(r1, 2)                        @ r1<- BBBB (high)
842    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
843    mov     r9, rINST, lsr #8           @ r9<- AA
844    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
845    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
846    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
847    cmp     r0, #0
848    beq     .LOP_CONST_STRING_JUMBO_resolve
849    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
851    SET_VREG(r0, r9)                    @ vAA<- r0
852    GOTO_OPCODE(ip)                     @ jump to next instruction
853
854/* ------------------------------ */
855    .balign 64
856.L_OP_CONST_CLASS: /* 0x1c */
857/* File: armv5te/OP_CONST_CLASS.S */
858    /* const/class vAA, Class@BBBB */
859    FETCH(r1, 1)                        @ r1<- BBBB
860    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
861    mov     r9, rINST, lsr #8           @ r9<- AA
862    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
863    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
864    cmp     r0, #0                      @ not yet resolved?
865    beq     .LOP_CONST_CLASS_resolve
866    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
867    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
868    SET_VREG(r0, r9)                    @ vAA<- r0
869    GOTO_OPCODE(ip)                     @ jump to next instruction
870
871/* ------------------------------ */
872    .balign 64
873.L_OP_MONITOR_ENTER: /* 0x1d */
874/* File: armv5te/OP_MONITOR_ENTER.S */
875    /*
876     * Synchronize on an object.
877     */
878    /* monitor-enter vAA */
879    mov     r2, rINST, lsr #8           @ r2<- AA
880    GET_VREG(r1, r2)                    @ r1<- vAA (object)
881    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
882    cmp     r1, #0                      @ null object?
883    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
884    beq     common_errNullObject        @ null object, throw an exception
885    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
886    bl      dvmLockObject               @ call(self, obj)
887#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
888    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
889    ldr     r1, [r0, #offThread_exception] @ check for exception
890    cmp     r1, #0
891    bne     common_exceptionThrown      @ exception raised, bail out
892#endif
893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
894    GOTO_OPCODE(ip)                     @ jump to next instruction
895
896/* ------------------------------ */
897    .balign 64
898.L_OP_MONITOR_EXIT: /* 0x1e */
899/* File: armv5te/OP_MONITOR_EXIT.S */
900    /*
901     * Unlock an object.
902     *
903     * Exceptions that occur when unlocking a monitor need to appear as
904     * if they happened at the following instruction.  See the Dalvik
905     * instruction spec.
906     */
907    /* monitor-exit vAA */
908    mov     r2, rINST, lsr #8           @ r2<- AA
909    EXPORT_PC()                         @ before fetch: export the PC
910    GET_VREG(r1, r2)                    @ r1<- vAA (object)
911    cmp     r1, #0                      @ null object?
912    beq     1f                          @ yes
913    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
914    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
915    cmp     r0, #0                      @ failed?
916    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
917    beq     common_exceptionThrown      @ yes, exception is pending
918    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
919    GOTO_OPCODE(ip)                     @ jump to next instruction
9201:
921    FETCH_ADVANCE_INST(1)               @ advance before throw
922    b      common_errNullObject
923
924/* ------------------------------ */
925    .balign 64
926.L_OP_CHECK_CAST: /* 0x1f */
927/* File: armv5te/OP_CHECK_CAST.S */
928    /*
929     * Check to see if a cast from one class to another is allowed.
930     */
931    /* check-cast vAA, class@BBBB */
932    mov     r3, rINST, lsr #8           @ r3<- AA
933    FETCH(r2, 1)                        @ r2<- BBBB
934    GET_VREG(r9, r3)                    @ r9<- object
935    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
936    cmp     r9, #0                      @ is object null?
937    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
938    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
939    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
940    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
941    cmp     r1, #0                      @ have we resolved this before?
942    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
943.LOP_CHECK_CAST_resolved:
944    cmp     r0, r1                      @ same class (trivial success)?
945    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
946.LOP_CHECK_CAST_okay:
947    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
948    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
949    GOTO_OPCODE(ip)                     @ jump to next instruction
950
951/* ------------------------------ */
952    .balign 64
953.L_OP_INSTANCE_OF: /* 0x20 */
954/* File: armv5te/OP_INSTANCE_OF.S */
955    /*
956     * Check to see if an object reference is an instance of a class.
957     *
958     * Most common situation is a non-null object, being compared against
959     * an already-resolved class.
960     */
961    /* instance-of vA, vB, class@CCCC */
962    mov     r3, rINST, lsr #12          @ r3<- B
963    mov     r9, rINST, lsr #8           @ r9<- A+
964    GET_VREG(r0, r3)                    @ r0<- vB (object)
965    and     r9, r9, #15                 @ r9<- A
966    cmp     r0, #0                      @ is object null?
967    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
968    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
969    FETCH(r3, 1)                        @ r3<- CCCC
970    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
971    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
972    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
973    cmp     r1, #0                      @ have we resolved this before?
974    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
975.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
976    cmp     r0, r1                      @ same class (trivial success)?
977    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
978    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
979
980/* ------------------------------ */
981    .balign 64
982.L_OP_ARRAY_LENGTH: /* 0x21 */
983/* File: armv6t2/OP_ARRAY_LENGTH.S */
984    /*
985     * Return the length of an array.
986     */
987    mov     r1, rINST, lsr #12          @ r1<- B
988    ubfx    r2, rINST, #8, #4           @ r2<- A
989    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
990    cmp     r0, #0                      @ is object null?
991    beq     common_errNullObject        @ yup, fail
992    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
993    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
994    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
995    SET_VREG(r3, r2)                    @ vB<- length
996    GOTO_OPCODE(ip)                     @ jump to next instruction
997
998/* ------------------------------ */
999    .balign 64
1000.L_OP_NEW_INSTANCE: /* 0x22 */
1001/* File: armv5te/OP_NEW_INSTANCE.S */
1002    /*
1003     * Create a new instance of a class.
1004     */
1005    /* new-instance vAA, class@BBBB */
1006    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1007    FETCH(r1, 1)                        @ r1<- BBBB
1008    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1009    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1010    EXPORT_PC()                         @ req'd for init, resolve, alloc
1011    cmp     r0, #0                      @ already resolved?
1012    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1013.LOP_NEW_INSTANCE_resolved:   @ r0=class
1014    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1015    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1016    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1017.LOP_NEW_INSTANCE_initialized: @ r0=class
1018    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1019    bl      dvmAllocObject              @ r0<- new object
1020    b       .LOP_NEW_INSTANCE_finish          @ continue
1021
1022/* ------------------------------ */
1023    .balign 64
1024.L_OP_NEW_ARRAY: /* 0x23 */
1025/* File: armv5te/OP_NEW_ARRAY.S */
1026    /*
1027     * Allocate an array of objects, specified with the array class
1028     * and a count.
1029     *
1030     * The verifier guarantees that this is an array class, so we don't
1031     * check for it here.
1032     */
1033    /* new-array vA, vB, class@CCCC */
1034    mov     r0, rINST, lsr #12          @ r0<- B
1035    FETCH(r2, 1)                        @ r2<- CCCC
1036    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1037    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1038    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1039    cmp     r1, #0                      @ check length
1040    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1041    bmi     common_errNegativeArraySize @ negative length, bail
1042    cmp     r0, #0                      @ already resolved?
1043    EXPORT_PC()                         @ req'd for resolve, alloc
1044    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1045    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1046
1047/* ------------------------------ */
1048    .balign 64
1049.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1050/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1051    /*
1052     * Create a new array with elements filled from registers.
1053     *
1054     * for: filled-new-array, filled-new-array/range
1055     */
1056    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1057    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1058    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1059    FETCH(r1, 1)                        @ r1<- BBBB
1060    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1061    EXPORT_PC()                         @ need for resolve and alloc
1062    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1063    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1064    cmp     r0, #0                      @ already resolved?
1065    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10668:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1067    mov     r2, #0                      @ r2<- false
1068    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1069    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1070    cmp     r0, #0                      @ got null?
1071    beq     common_exceptionThrown      @ yes, handle exception
1072    b       .LOP_FILLED_NEW_ARRAY_continue
1073
1074/* ------------------------------ */
1075    .balign 64
1076.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1077/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1078/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1079    /*
1080     * Create a new array with elements filled from registers.
1081     *
1082     * for: filled-new-array, filled-new-array/range
1083     */
1084    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1085    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1086    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1087    FETCH(r1, 1)                        @ r1<- BBBB
1088    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1089    EXPORT_PC()                         @ need for resolve and alloc
1090    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1091    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1092    cmp     r0, #0                      @ already resolved?
1093    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10948:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1095    mov     r2, #0                      @ r2<- false
1096    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1097    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1098    cmp     r0, #0                      @ got null?
1099    beq     common_exceptionThrown      @ yes, handle exception
1100    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1101
1102
1103/* ------------------------------ */
1104    .balign 64
1105.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1106/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1107    /* fill-array-data vAA, +BBBBBBBB */
1108    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1109    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1110    mov     r3, rINST, lsr #8           @ r3<- AA
1111    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1112    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1113    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1114    EXPORT_PC();
1115    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1116    cmp     r0, #0                      @ 0 means an exception is thrown
1117    beq     common_exceptionThrown      @ has exception
1118    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1119    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1120    GOTO_OPCODE(ip)                     @ jump to next instruction
1121
1122/* ------------------------------ */
1123    .balign 64
1124.L_OP_THROW: /* 0x27 */
1125/* File: armv5te/OP_THROW.S */
1126    /*
1127     * Throw an exception object in the current thread.
1128     */
1129    /* throw vAA */
1130    mov     r2, rINST, lsr #8           @ r2<- AA
1131    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1132    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1133    EXPORT_PC()                         @ exception handler can throw
1134    cmp     r1, #0                      @ null object?
1135    beq     common_errNullObject        @ yes, throw an NPE instead
1136    @ bypass dvmSetException, just store it
1137    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1138    b       common_exceptionThrown
1139
1140/* ------------------------------ */
1141    .balign 64
1142.L_OP_GOTO: /* 0x28 */
1143/* File: armv5te/OP_GOTO.S */
1144    /*
1145     * Unconditional branch, 8-bit offset.
1146     *
1147     * The branch distance is a signed code-unit offset, which we need to
1148     * double to get a byte offset.
1149     */
1150    /* goto +AA */
1151    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1152    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1153    mov     r9, r9, lsl #1              @ r9<- byte offset
1154    bmi     common_backwardBranch       @ backward branch, do periodic checks
1155#if defined(WITH_JIT)
1156    GET_JIT_PROF_TABLE(r0)
1157    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1158    cmp     r0,#0
1159    bne     common_updateProfile
1160    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1161    GOTO_OPCODE(ip)                     @ jump to next instruction
1162#else
1163    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1164    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1165    GOTO_OPCODE(ip)                     @ jump to next instruction
1166#endif
1167
1168/* ------------------------------ */
1169    .balign 64
1170.L_OP_GOTO_16: /* 0x29 */
1171/* File: armv5te/OP_GOTO_16.S */
1172    /*
1173     * Unconditional branch, 16-bit offset.
1174     *
1175     * The branch distance is a signed code-unit offset, which we need to
1176     * double to get a byte offset.
1177     */
1178    /* goto/16 +AAAA */
1179    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1180    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1181    bmi     common_backwardBranch       @ backward branch, do periodic checks
1182#if defined(WITH_JIT)
1183    GET_JIT_PROF_TABLE(r0)
1184    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1185    cmp     r0,#0
1186    bne     common_updateProfile
1187    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1188    GOTO_OPCODE(ip)                     @ jump to next instruction
1189#else
1190    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1191    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1192    GOTO_OPCODE(ip)                     @ jump to next instruction
1193#endif
1194
1195/* ------------------------------ */
1196    .balign 64
1197.L_OP_GOTO_32: /* 0x2a */
1198/* File: armv5te/OP_GOTO_32.S */
1199    /*
1200     * Unconditional branch, 32-bit offset.
1201     *
1202     * The branch distance is a signed code-unit offset, which we need to
1203     * double to get a byte offset.
1204     *
1205     * Unlike most opcodes, this one is allowed to branch to itself, so
1206     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1207     * instruction doesn't affect the V flag, so we need to clear it
1208     * explicitly.
1209     */
1210    /* goto/32 +AAAAAAAA */
1211    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1212    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1213    cmp     ip, ip                      @ (clear V flag during stall)
1214    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1215    mov     r9, r0, asl #1              @ r9<- byte offset
1216    ble     common_backwardBranch       @ backward branch, do periodic checks
1217#if defined(WITH_JIT)
1218    GET_JIT_PROF_TABLE(r0)
1219    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1220    cmp     r0,#0
1221    bne     common_updateProfile
1222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1223    GOTO_OPCODE(ip)                     @ jump to next instruction
1224#else
1225    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1226    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1227    GOTO_OPCODE(ip)                     @ jump to next instruction
1228#endif
1229
1230/* ------------------------------ */
1231    .balign 64
1232.L_OP_PACKED_SWITCH: /* 0x2b */
1233/* File: armv5te/OP_PACKED_SWITCH.S */
1234    /*
1235     * Handle a packed-switch or sparse-switch instruction.  In both cases
1236     * we decode it and hand it off to a helper function.
1237     *
1238     * We don't really expect backward branches in a switch statement, but
1239     * they're perfectly legal, so we check for them here.
1240     *
1241     * for: packed-switch, sparse-switch
1242     */
1243    /* op vAA, +BBBB */
1244    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1245    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1246    mov     r3, rINST, lsr #8           @ r3<- AA
1247    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1248    GET_VREG(r1, r3)                    @ r1<- vAA
1249    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1250    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1251    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1252    bmi     common_backwardBranch       @ backward branch, do periodic checks
1253    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1254#if defined(WITH_JIT)
1255    GET_JIT_PROF_TABLE(r0)
1256    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1257    cmp     r0,#0
1258    bne     common_updateProfile
1259    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1260    GOTO_OPCODE(ip)                     @ jump to next instruction
1261#else
1262    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1264    GOTO_OPCODE(ip)                     @ jump to next instruction
1265#endif
1266
1267/* ------------------------------ */
1268    .balign 64
1269.L_OP_SPARSE_SWITCH: /* 0x2c */
1270/* File: armv5te/OP_SPARSE_SWITCH.S */
1271/* File: armv5te/OP_PACKED_SWITCH.S */
1272    /*
1273     * Handle a packed-switch or sparse-switch instruction.  In both cases
1274     * we decode it and hand it off to a helper function.
1275     *
1276     * We don't really expect backward branches in a switch statement, but
1277     * they're perfectly legal, so we check for them here.
1278     *
1279     * for: packed-switch, sparse-switch
1280     */
1281    /* op vAA, +BBBB */
1282    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1283    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1284    mov     r3, rINST, lsr #8           @ r3<- AA
1285    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1286    GET_VREG(r1, r3)                    @ r1<- vAA
1287    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1288    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1289    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1290    bmi     common_backwardBranch       @ backward branch, do periodic checks
1291    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1292#if defined(WITH_JIT)
1293    GET_JIT_PROF_TABLE(r0)
1294    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1295    cmp     r0,#0
1296    bne     common_updateProfile
1297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1298    GOTO_OPCODE(ip)                     @ jump to next instruction
1299#else
1300    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1301    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1302    GOTO_OPCODE(ip)                     @ jump to next instruction
1303#endif
1304
1305
1306/* ------------------------------ */
1307    .balign 64
1308.L_OP_CMPL_FLOAT: /* 0x2d */
1309/* File: arm-vfp/OP_CMPL_FLOAT.S */
1310    /*
1311     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1312     * destination register based on the results of the comparison.
1313     *
1314     * int compare(x, y) {
1315     *     if (x == y) {
1316     *         return 0;
1317     *     } else if (x > y) {
1318     *         return 1;
1319     *     } else if (x < y) {
1320     *         return -1;
1321     *     } else {
1322     *         return -1;
1323     *     }
1324     * }
1325     */
1326    /* op vAA, vBB, vCC */
1327    FETCH(r0, 1)                        @ r0<- CCBB
1328    mov     r9, rINST, lsr #8           @ r9<- AA
1329    and     r2, r0, #255                @ r2<- BB
1330    mov     r3, r0, lsr #8              @ r3<- CC
1331    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1332    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1333    flds    s0, [r2]                    @ s0<- vBB
1334    flds    s1, [r3]                    @ s1<- vCC
1335    fcmpes  s0, s1                      @ compare (vBB, vCC)
1336    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1337    mvn     r0, #0                      @ r0<- -1 (default)
1338    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1339    fmstat                              @ export status flags
1340    movgt   r0, #1                      @ (greater than) r1<- 1
1341    moveq   r0, #0                      @ (equal) r1<- 0
1342    b       .LOP_CMPL_FLOAT_finish          @ argh
1343
1344
1345/* ------------------------------ */
1346    .balign 64
1347.L_OP_CMPG_FLOAT: /* 0x2e */
1348/* File: arm-vfp/OP_CMPG_FLOAT.S */
1349    /*
1350     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1351     * destination register based on the results of the comparison.
1352     *
1353     * int compare(x, y) {
1354     *     if (x == y) {
1355     *         return 0;
1356     *     } else if (x < y) {
1357     *         return -1;
1358     *     } else if (x > y) {
1359     *         return 1;
1360     *     } else {
1361     *         return 1;
1362     *     }
1363     * }
1364     */
1365    /* op vAA, vBB, vCC */
1366    FETCH(r0, 1)                        @ r0<- CCBB
1367    mov     r9, rINST, lsr #8           @ r9<- AA
1368    and     r2, r0, #255                @ r2<- BB
1369    mov     r3, r0, lsr #8              @ r3<- CC
1370    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1371    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1372    flds    s0, [r2]                    @ s0<- vBB
1373    flds    s1, [r3]                    @ s1<- vCC
1374    fcmpes  s0, s1                      @ compare (vBB, vCC)
1375    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1376    mov     r0, #1                      @ r0<- 1 (default)
1377    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1378    fmstat                              @ export status flags
1379    mvnmi   r0, #0                      @ (less than) r1<- -1
1380    moveq   r0, #0                      @ (equal) r1<- 0
1381    b       .LOP_CMPG_FLOAT_finish          @ argh
1382
1383
1384/* ------------------------------ */
1385    .balign 64
1386.L_OP_CMPL_DOUBLE: /* 0x2f */
1387/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1388    /*
1389     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1390     * destination register based on the results of the comparison.
1391     *
1392     * int compare(x, y) {
1393     *     if (x == y) {
1394     *         return 0;
1395     *     } else if (x > y) {
1396     *         return 1;
1397     *     } else if (x < y) {
1398     *         return -1;
1399     *     } else {
1400     *         return -1;
1401     *     }
1402     * }
1403     */
1404    /* op vAA, vBB, vCC */
1405    FETCH(r0, 1)                        @ r0<- CCBB
1406    mov     r9, rINST, lsr #8           @ r9<- AA
1407    and     r2, r0, #255                @ r2<- BB
1408    mov     r3, r0, lsr #8              @ r3<- CC
1409    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1410    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1411    fldd    d0, [r2]                    @ d0<- vBB
1412    fldd    d1, [r3]                    @ d1<- vCC
1413    fcmped  d0, d1                      @ compare (vBB, vCC)
1414    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1415    mvn     r0, #0                      @ r0<- -1 (default)
1416    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1417    fmstat                              @ export status flags
1418    movgt   r0, #1                      @ (greater than) r1<- 1
1419    moveq   r0, #0                      @ (equal) r1<- 0
1420    b       .LOP_CMPL_DOUBLE_finish          @ argh
1421
1422
1423/* ------------------------------ */
1424    .balign 64
1425.L_OP_CMPG_DOUBLE: /* 0x30 */
1426/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1427    /*
1428     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1429     * destination register based on the results of the comparison.
1430     *
1431     * int compare(x, y) {
1432     *     if (x == y) {
1433     *         return 0;
1434     *     } else if (x < y) {
1435     *         return -1;
1436     *     } else if (x > y) {
1437     *         return 1;
1438     *     } else {
1439     *         return 1;
1440     *     }
1441     * }
1442     */
1443    /* op vAA, vBB, vCC */
1444    FETCH(r0, 1)                        @ r0<- CCBB
1445    mov     r9, rINST, lsr #8           @ r9<- AA
1446    and     r2, r0, #255                @ r2<- BB
1447    mov     r3, r0, lsr #8              @ r3<- CC
1448    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1449    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1450    fldd    d0, [r2]                    @ d0<- vBB
1451    fldd    d1, [r3]                    @ d1<- vCC
1452    fcmped  d0, d1                      @ compare (vBB, vCC)
1453    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1454    mov     r0, #1                      @ r0<- 1 (default)
1455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1456    fmstat                              @ export status flags
1457    mvnmi   r0, #0                      @ (less than) r1<- -1
1458    moveq   r0, #0                      @ (equal) r1<- 0
1459    b       .LOP_CMPG_DOUBLE_finish          @ argh
1460
1461
1462/* ------------------------------ */
1463    .balign 64
1464.L_OP_CMP_LONG: /* 0x31 */
1465/* File: armv5te/OP_CMP_LONG.S */
1466    /*
1467     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1468     * register based on the results of the comparison.
1469     *
1470     * We load the full values with LDM, but in practice many values could
1471     * be resolved by only looking at the high word.  This could be made
1472     * faster or slower by splitting the LDM into a pair of LDRs.
1473     *
1474     * If we just wanted to set condition flags, we could do this:
1475     *  subs    ip, r0, r2
1476     *  sbcs    ip, r1, r3
1477     *  subeqs  ip, r0, r2
1478     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1479     * integer value, which we can do with 2 conditional mov/mvn instructions
1480     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1481     * us a constant 5-cycle path plus a branch at the end to the
1482     * instruction epilogue code.  The multi-compare approach below needs
1483     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1484     * in the worst case (the 64-bit values are equal).
1485     */
1486    /* cmp-long vAA, vBB, vCC */
1487    FETCH(r0, 1)                        @ r0<- CCBB
1488    mov     r9, rINST, lsr #8           @ r9<- AA
1489    and     r2, r0, #255                @ r2<- BB
1490    mov     r3, r0, lsr #8              @ r3<- CC
1491    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1492    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1493    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1494    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1495    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1496    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1497    bgt     .LOP_CMP_LONG_greater
1498    subs    r1, r0, r2                  @ r1<- r0 - r2
1499    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1500    bne     .LOP_CMP_LONG_less
1501    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1502
1503/* ------------------------------ */
1504    .balign 64
1505.L_OP_IF_EQ: /* 0x32 */
1506/* File: armv6t2/OP_IF_EQ.S */
1507/* File: armv6t2/bincmp.S */
1508    /*
1509     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1510     * fragment that specifies the *reverse* comparison to perform, e.g.
1511     * for "if-le" you would use "gt".
1512     *
1513     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1514     */
1515    /* if-cmp vA, vB, +CCCC */
1516    mov     r1, rINST, lsr #12          @ r1<- B
1517    ubfx    r0, rINST, #8, #4           @ r0<- A
1518    GET_VREG(r3, r1)                    @ r3<- vB
1519    GET_VREG(r2, r0)                    @ r2<- vA
1520    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1521    cmp     r2, r3                      @ compare (vA, vB)
1522    bne  1f                      @ branch to 1 if comparison failed
1523    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1524    movs    r9, r9, asl #1              @ convert to bytes, check sign
1525    bmi     common_backwardBranch       @ yes, do periodic checks
15261:
1527#if defined(WITH_JIT)
1528    GET_JIT_PROF_TABLE(r0)
1529    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1530    b        common_testUpdateProfile
1531#else
1532    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1533    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1534    GOTO_OPCODE(ip)                     @ jump to next instruction
1535#endif
1536
1537
1538/* ------------------------------ */
1539    .balign 64
1540.L_OP_IF_NE: /* 0x33 */
1541/* File: armv6t2/OP_IF_NE.S */
1542/* File: armv6t2/bincmp.S */
1543    /*
1544     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1545     * fragment that specifies the *reverse* comparison to perform, e.g.
1546     * for "if-le" you would use "gt".
1547     *
1548     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1549     */
1550    /* if-cmp vA, vB, +CCCC */
1551    mov     r1, rINST, lsr #12          @ r1<- B
1552    ubfx    r0, rINST, #8, #4           @ r0<- A
1553    GET_VREG(r3, r1)                    @ r3<- vB
1554    GET_VREG(r2, r0)                    @ r2<- vA
1555    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1556    cmp     r2, r3                      @ compare (vA, vB)
1557    beq  1f                      @ branch to 1 if comparison failed
1558    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1559    movs    r9, r9, asl #1              @ convert to bytes, check sign
1560    bmi     common_backwardBranch       @ yes, do periodic checks
15611:
1562#if defined(WITH_JIT)
1563    GET_JIT_PROF_TABLE(r0)
1564    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1565    b        common_testUpdateProfile
1566#else
1567    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1568    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1569    GOTO_OPCODE(ip)                     @ jump to next instruction
1570#endif
1571
1572
1573/* ------------------------------ */
1574    .balign 64
1575.L_OP_IF_LT: /* 0x34 */
1576/* File: armv6t2/OP_IF_LT.S */
1577/* File: armv6t2/bincmp.S */
1578    /*
1579     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1580     * fragment that specifies the *reverse* comparison to perform, e.g.
1581     * for "if-le" you would use "gt".
1582     *
1583     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1584     */
1585    /* if-cmp vA, vB, +CCCC */
1586    mov     r1, rINST, lsr #12          @ r1<- B
1587    ubfx    r0, rINST, #8, #4           @ r0<- A
1588    GET_VREG(r3, r1)                    @ r3<- vB
1589    GET_VREG(r2, r0)                    @ r2<- vA
1590    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1591    cmp     r2, r3                      @ compare (vA, vB)
1592    bge  1f                      @ branch to 1 if comparison failed
1593    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1594    movs    r9, r9, asl #1              @ convert to bytes, check sign
1595    bmi     common_backwardBranch       @ yes, do periodic checks
15961:
1597#if defined(WITH_JIT)
1598    GET_JIT_PROF_TABLE(r0)
1599    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1600    b        common_testUpdateProfile
1601#else
1602    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1603    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1604    GOTO_OPCODE(ip)                     @ jump to next instruction
1605#endif
1606
1607
1608/* ------------------------------ */
1609    .balign 64
1610.L_OP_IF_GE: /* 0x35 */
1611/* File: armv6t2/OP_IF_GE.S */
1612/* File: armv6t2/bincmp.S */
1613    /*
1614     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1615     * fragment that specifies the *reverse* comparison to perform, e.g.
1616     * for "if-le" you would use "gt".
1617     *
1618     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1619     */
1620    /* if-cmp vA, vB, +CCCC */
1621    mov     r1, rINST, lsr #12          @ r1<- B
1622    ubfx    r0, rINST, #8, #4           @ r0<- A
1623    GET_VREG(r3, r1)                    @ r3<- vB
1624    GET_VREG(r2, r0)                    @ r2<- vA
1625    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1626    cmp     r2, r3                      @ compare (vA, vB)
1627    blt  1f                      @ branch to 1 if comparison failed
1628    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1629    movs    r9, r9, asl #1              @ convert to bytes, check sign
1630    bmi     common_backwardBranch       @ yes, do periodic checks
16311:
1632#if defined(WITH_JIT)
1633    GET_JIT_PROF_TABLE(r0)
1634    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1635    b        common_testUpdateProfile
1636#else
1637    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1638    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1639    GOTO_OPCODE(ip)                     @ jump to next instruction
1640#endif
1641
1642
1643/* ------------------------------ */
1644    .balign 64
1645.L_OP_IF_GT: /* 0x36 */
1646/* File: armv6t2/OP_IF_GT.S */
1647/* File: armv6t2/bincmp.S */
1648    /*
1649     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1650     * fragment that specifies the *reverse* comparison to perform, e.g.
1651     * for "if-le" you would use "gt".
1652     *
1653     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1654     */
1655    /* if-cmp vA, vB, +CCCC */
1656    mov     r1, rINST, lsr #12          @ r1<- B
1657    ubfx    r0, rINST, #8, #4           @ r0<- A
1658    GET_VREG(r3, r1)                    @ r3<- vB
1659    GET_VREG(r2, r0)                    @ r2<- vA
1660    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1661    cmp     r2, r3                      @ compare (vA, vB)
1662    ble  1f                      @ branch to 1 if comparison failed
1663    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1664    movs    r9, r9, asl #1              @ convert to bytes, check sign
1665    bmi     common_backwardBranch       @ yes, do periodic checks
16661:
1667#if defined(WITH_JIT)
1668    GET_JIT_PROF_TABLE(r0)
1669    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1670    b        common_testUpdateProfile
1671#else
1672    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1674    GOTO_OPCODE(ip)                     @ jump to next instruction
1675#endif
1676
1677
1678/* ------------------------------ */
1679    .balign 64
1680.L_OP_IF_LE: /* 0x37 */
1681/* File: armv6t2/OP_IF_LE.S */
1682/* File: armv6t2/bincmp.S */
1683    /*
1684     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1685     * fragment that specifies the *reverse* comparison to perform, e.g.
1686     * for "if-le" you would use "gt".
1687     *
1688     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1689     */
1690    /* if-cmp vA, vB, +CCCC */
1691    mov     r1, rINST, lsr #12          @ r1<- B
1692    ubfx    r0, rINST, #8, #4           @ r0<- A
1693    GET_VREG(r3, r1)                    @ r3<- vB
1694    GET_VREG(r2, r0)                    @ r2<- vA
1695    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1696    cmp     r2, r3                      @ compare (vA, vB)
1697    bgt  1f                      @ branch to 1 if comparison failed
1698    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1699    movs    r9, r9, asl #1              @ convert to bytes, check sign
1700    bmi     common_backwardBranch       @ yes, do periodic checks
17011:
1702#if defined(WITH_JIT)
1703    GET_JIT_PROF_TABLE(r0)
1704    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1705    b        common_testUpdateProfile
1706#else
1707    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1708    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1709    GOTO_OPCODE(ip)                     @ jump to next instruction
1710#endif
1711
1712
1713/* ------------------------------ */
1714    .balign 64
1715.L_OP_IF_EQZ: /* 0x38 */
1716/* File: armv5te/OP_IF_EQZ.S */
1717/* File: armv5te/zcmp.S */
1718    /*
1719     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1720     * fragment that specifies the *reverse* comparison to perform, e.g.
1721     * for "if-le" you would use "gt".
1722     *
1723     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1724     */
1725    /* if-cmp vAA, +BBBB */
1726    mov     r0, rINST, lsr #8           @ r0<- AA
1727    GET_VREG(r2, r0)                    @ r2<- vAA
1728    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1729    cmp     r2, #0                      @ compare (vA, 0)
1730    bne  1f                      @ branch to 1 if comparison failed
1731    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1732    movs    r9, r9, asl #1              @ convert to bytes, check sign
1733    bmi     common_backwardBranch       @ backward branch, do periodic checks
17341:
1735#if defined(WITH_JIT)
1736    GET_JIT_PROF_TABLE(r0)
1737    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1738    cmp     r0,#0
1739    bne     common_updateProfile
1740    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1741    GOTO_OPCODE(ip)                     @ jump to next instruction
1742#else
1743    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1744    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1745    GOTO_OPCODE(ip)                     @ jump to next instruction
1746#endif
1747
1748
1749/* ------------------------------ */
1750    .balign 64
1751.L_OP_IF_NEZ: /* 0x39 */
1752/* File: armv5te/OP_IF_NEZ.S */
1753/* File: armv5te/zcmp.S */
1754    /*
1755     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1756     * fragment that specifies the *reverse* comparison to perform, e.g.
1757     * for "if-le" you would use "gt".
1758     *
1759     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1760     */
1761    /* if-cmp vAA, +BBBB */
1762    mov     r0, rINST, lsr #8           @ r0<- AA
1763    GET_VREG(r2, r0)                    @ r2<- vAA
1764    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1765    cmp     r2, #0                      @ compare (vA, 0)
1766    beq  1f                      @ branch to 1 if comparison failed
1767    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1768    movs    r9, r9, asl #1              @ convert to bytes, check sign
1769    bmi     common_backwardBranch       @ backward branch, do periodic checks
17701:
1771#if defined(WITH_JIT)
1772    GET_JIT_PROF_TABLE(r0)
1773    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1774    cmp     r0,#0
1775    bne     common_updateProfile
1776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1777    GOTO_OPCODE(ip)                     @ jump to next instruction
1778#else
1779    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1781    GOTO_OPCODE(ip)                     @ jump to next instruction
1782#endif
1783
1784
1785/* ------------------------------ */
1786    .balign 64
1787.L_OP_IF_LTZ: /* 0x3a */
1788/* File: armv5te/OP_IF_LTZ.S */
1789/* File: armv5te/zcmp.S */
1790    /*
1791     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1792     * fragment that specifies the *reverse* comparison to perform, e.g.
1793     * for "if-le" you would use "gt".
1794     *
1795     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1796     */
1797    /* if-cmp vAA, +BBBB */
1798    mov     r0, rINST, lsr #8           @ r0<- AA
1799    GET_VREG(r2, r0)                    @ r2<- vAA
1800    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1801    cmp     r2, #0                      @ compare (vA, 0)
1802    bge  1f                      @ branch to 1 if comparison failed
1803    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1804    movs    r9, r9, asl #1              @ convert to bytes, check sign
1805    bmi     common_backwardBranch       @ backward branch, do periodic checks
18061:
1807#if defined(WITH_JIT)
1808    GET_JIT_PROF_TABLE(r0)
1809    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1810    cmp     r0,#0
1811    bne     common_updateProfile
1812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1813    GOTO_OPCODE(ip)                     @ jump to next instruction
1814#else
1815    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1817    GOTO_OPCODE(ip)                     @ jump to next instruction
1818#endif
1819
1820
1821/* ------------------------------ */
1822    .balign 64
1823.L_OP_IF_GEZ: /* 0x3b */
1824/* File: armv5te/OP_IF_GEZ.S */
1825/* File: armv5te/zcmp.S */
1826    /*
1827     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1828     * fragment that specifies the *reverse* comparison to perform, e.g.
1829     * for "if-le" you would use "gt".
1830     *
1831     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1832     */
1833    /* if-cmp vAA, +BBBB */
1834    mov     r0, rINST, lsr #8           @ r0<- AA
1835    GET_VREG(r2, r0)                    @ r2<- vAA
1836    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1837    cmp     r2, #0                      @ compare (vA, 0)
1838    blt  1f                      @ branch to 1 if comparison failed
1839    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1840    movs    r9, r9, asl #1              @ convert to bytes, check sign
1841    bmi     common_backwardBranch       @ backward branch, do periodic checks
18421:
1843#if defined(WITH_JIT)
1844    GET_JIT_PROF_TABLE(r0)
1845    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1846    cmp     r0,#0
1847    bne     common_updateProfile
1848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1849    GOTO_OPCODE(ip)                     @ jump to next instruction
1850#else
1851    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1852    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1853    GOTO_OPCODE(ip)                     @ jump to next instruction
1854#endif
1855
1856
1857/* ------------------------------ */
1858    .balign 64
1859.L_OP_IF_GTZ: /* 0x3c */
1860/* File: armv5te/OP_IF_GTZ.S */
1861/* File: armv5te/zcmp.S */
1862    /*
1863     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1864     * fragment that specifies the *reverse* comparison to perform, e.g.
1865     * for "if-le" you would use "gt".
1866     *
1867     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1868     */
1869    /* if-cmp vAA, +BBBB */
1870    mov     r0, rINST, lsr #8           @ r0<- AA
1871    GET_VREG(r2, r0)                    @ r2<- vAA
1872    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1873    cmp     r2, #0                      @ compare (vA, 0)
1874    ble  1f                      @ branch to 1 if comparison failed
1875    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1876    movs    r9, r9, asl #1              @ convert to bytes, check sign
1877    bmi     common_backwardBranch       @ backward branch, do periodic checks
18781:
1879#if defined(WITH_JIT)
1880    GET_JIT_PROF_TABLE(r0)
1881    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1882    cmp     r0,#0
1883    bne     common_updateProfile
1884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1885    GOTO_OPCODE(ip)                     @ jump to next instruction
1886#else
1887    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1889    GOTO_OPCODE(ip)                     @ jump to next instruction
1890#endif
1891
1892
1893/* ------------------------------ */
1894    .balign 64
1895.L_OP_IF_LEZ: /* 0x3d */
1896/* File: armv5te/OP_IF_LEZ.S */
1897/* File: armv5te/zcmp.S */
1898    /*
1899     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1900     * fragment that specifies the *reverse* comparison to perform, e.g.
1901     * for "if-le" you would use "gt".
1902     *
1903     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1904     */
1905    /* if-cmp vAA, +BBBB */
1906    mov     r0, rINST, lsr #8           @ r0<- AA
1907    GET_VREG(r2, r0)                    @ r2<- vAA
1908    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1909    cmp     r2, #0                      @ compare (vA, 0)
1910    bgt  1f                      @ branch to 1 if comparison failed
1911    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1912    movs    r9, r9, asl #1              @ convert to bytes, check sign
1913    bmi     common_backwardBranch       @ backward branch, do periodic checks
19141:
1915#if defined(WITH_JIT)
1916    GET_JIT_PROF_TABLE(r0)
1917    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1918    cmp     r0,#0
1919    bne     common_updateProfile
1920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1921    GOTO_OPCODE(ip)                     @ jump to next instruction
1922#else
1923    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1925    GOTO_OPCODE(ip)                     @ jump to next instruction
1926#endif
1927
1928
1929/* ------------------------------ */
1930    .balign 64
1931.L_OP_UNUSED_3E: /* 0x3e */
1932/* File: armv5te/OP_UNUSED_3E.S */
1933/* File: armv5te/unused.S */
1934    bl      common_abort
1935
1936
1937/* ------------------------------ */
1938    .balign 64
1939.L_OP_UNUSED_3F: /* 0x3f */
1940/* File: armv5te/OP_UNUSED_3F.S */
1941/* File: armv5te/unused.S */
1942    bl      common_abort
1943
1944
1945/* ------------------------------ */
1946    .balign 64
1947.L_OP_UNUSED_40: /* 0x40 */
1948/* File: armv5te/OP_UNUSED_40.S */
1949/* File: armv5te/unused.S */
1950    bl      common_abort
1951
1952
1953/* ------------------------------ */
1954    .balign 64
1955.L_OP_UNUSED_41: /* 0x41 */
1956/* File: armv5te/OP_UNUSED_41.S */
1957/* File: armv5te/unused.S */
1958    bl      common_abort
1959
1960
1961/* ------------------------------ */
1962    .balign 64
1963.L_OP_UNUSED_42: /* 0x42 */
1964/* File: armv5te/OP_UNUSED_42.S */
1965/* File: armv5te/unused.S */
1966    bl      common_abort
1967
1968
1969/* ------------------------------ */
1970    .balign 64
1971.L_OP_UNUSED_43: /* 0x43 */
1972/* File: armv5te/OP_UNUSED_43.S */
1973/* File: armv5te/unused.S */
1974    bl      common_abort
1975
1976
1977/* ------------------------------ */
1978    .balign 64
1979.L_OP_AGET: /* 0x44 */
1980/* File: armv5te/OP_AGET.S */
1981    /*
1982     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1983     *
1984     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1985     * instructions.  We use a pair of FETCH_Bs instead.
1986     *
1987     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1988     */
1989    /* op vAA, vBB, vCC */
1990    FETCH_B(r2, 1, 0)                   @ r2<- BB
1991    mov     r9, rINST, lsr #8           @ r9<- AA
1992    FETCH_B(r3, 1, 1)                   @ r3<- CC
1993    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1994    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1995    cmp     r0, #0                      @ null array object?
1996    beq     common_errNullObject        @ yes, bail
1997    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1998    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1999    cmp     r1, r3                      @ compare unsigned index, length
2000    bcs     common_errArrayIndex        @ index >= length, bail
2001    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2002    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2003    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2004    SET_VREG(r2, r9)                    @ vAA<- r2
2005    GOTO_OPCODE(ip)                     @ jump to next instruction
2006
2007/* ------------------------------ */
2008    .balign 64
2009.L_OP_AGET_WIDE: /* 0x45 */
2010/* File: armv5te/OP_AGET_WIDE.S */
2011    /*
2012     * Array get, 64 bits.  vAA <- vBB[vCC].
2013     *
2014     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2015     */
2016    /* aget-wide vAA, vBB, vCC */
2017    FETCH(r0, 1)                        @ r0<- CCBB
2018    mov     r9, rINST, lsr #8           @ r9<- AA
2019    and     r2, r0, #255                @ r2<- BB
2020    mov     r3, r0, lsr #8              @ r3<- CC
2021    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2022    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2023    cmp     r0, #0                      @ null array object?
2024    beq     common_errNullObject        @ yes, bail
2025    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2026    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2027    cmp     r1, r3                      @ compare unsigned index, length
2028    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2029    b       common_errArrayIndex        @ index >= length, bail
2030    @ May want to swap the order of these two branches depending on how the
2031    @ branch prediction (if any) handles conditional forward branches vs.
2032    @ unconditional forward branches.
2033
2034/* ------------------------------ */
2035    .balign 64
2036.L_OP_AGET_OBJECT: /* 0x46 */
2037/* File: armv5te/OP_AGET_OBJECT.S */
2038/* File: armv5te/OP_AGET.S */
2039    /*
2040     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2041     *
2042     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2043     * instructions.  We use a pair of FETCH_Bs instead.
2044     *
2045     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2046     */
2047    /* op vAA, vBB, vCC */
2048    FETCH_B(r2, 1, 0)                   @ r2<- BB
2049    mov     r9, rINST, lsr #8           @ r9<- AA
2050    FETCH_B(r3, 1, 1)                   @ r3<- CC
2051    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2052    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2053    cmp     r0, #0                      @ null array object?
2054    beq     common_errNullObject        @ yes, bail
2055    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2056    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2057    cmp     r1, r3                      @ compare unsigned index, length
2058    bcs     common_errArrayIndex        @ index >= length, bail
2059    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2060    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2061    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2062    SET_VREG(r2, r9)                    @ vAA<- r2
2063    GOTO_OPCODE(ip)                     @ jump to next instruction
2064
2065
2066/* ------------------------------ */
2067    .balign 64
2068.L_OP_AGET_BOOLEAN: /* 0x47 */
2069/* File: armv5te/OP_AGET_BOOLEAN.S */
2070/* File: armv5te/OP_AGET.S */
2071    /*
2072     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2073     *
2074     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2075     * instructions.  We use a pair of FETCH_Bs instead.
2076     *
2077     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2078     */
2079    /* op vAA, vBB, vCC */
2080    FETCH_B(r2, 1, 0)                   @ r2<- BB
2081    mov     r9, rINST, lsr #8           @ r9<- AA
2082    FETCH_B(r3, 1, 1)                   @ r3<- CC
2083    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2084    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2085    cmp     r0, #0                      @ null array object?
2086    beq     common_errNullObject        @ yes, bail
2087    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2088    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2089    cmp     r1, r3                      @ compare unsigned index, length
2090    bcs     common_errArrayIndex        @ index >= length, bail
2091    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2092    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2093    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2094    SET_VREG(r2, r9)                    @ vAA<- r2
2095    GOTO_OPCODE(ip)                     @ jump to next instruction
2096
2097
2098/* ------------------------------ */
2099    .balign 64
2100.L_OP_AGET_BYTE: /* 0x48 */
2101/* File: armv5te/OP_AGET_BYTE.S */
2102/* File: armv5te/OP_AGET.S */
2103    /*
2104     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2105     *
2106     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2107     * instructions.  We use a pair of FETCH_Bs instead.
2108     *
2109     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2110     */
2111    /* op vAA, vBB, vCC */
2112    FETCH_B(r2, 1, 0)                   @ r2<- BB
2113    mov     r9, rINST, lsr #8           @ r9<- AA
2114    FETCH_B(r3, 1, 1)                   @ r3<- CC
2115    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2116    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2117    cmp     r0, #0                      @ null array object?
2118    beq     common_errNullObject        @ yes, bail
2119    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2120    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2121    cmp     r1, r3                      @ compare unsigned index, length
2122    bcs     common_errArrayIndex        @ index >= length, bail
2123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2124    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2125    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2126    SET_VREG(r2, r9)                    @ vAA<- r2
2127    GOTO_OPCODE(ip)                     @ jump to next instruction
2128
2129
2130/* ------------------------------ */
2131    .balign 64
2132.L_OP_AGET_CHAR: /* 0x49 */
2133/* File: armv5te/OP_AGET_CHAR.S */
2134/* File: armv5te/OP_AGET.S */
2135    /*
2136     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2137     *
2138     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2139     * instructions.  We use a pair of FETCH_Bs instead.
2140     *
2141     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2142     */
2143    /* op vAA, vBB, vCC */
2144    FETCH_B(r2, 1, 0)                   @ r2<- BB
2145    mov     r9, rINST, lsr #8           @ r9<- AA
2146    FETCH_B(r3, 1, 1)                   @ r3<- CC
2147    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2148    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2149    cmp     r0, #0                      @ null array object?
2150    beq     common_errNullObject        @ yes, bail
2151    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2152    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2153    cmp     r1, r3                      @ compare unsigned index, length
2154    bcs     common_errArrayIndex        @ index >= length, bail
2155    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2156    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2158    SET_VREG(r2, r9)                    @ vAA<- r2
2159    GOTO_OPCODE(ip)                     @ jump to next instruction
2160
2161
2162/* ------------------------------ */
2163    .balign 64
2164.L_OP_AGET_SHORT: /* 0x4a */
2165/* File: armv5te/OP_AGET_SHORT.S */
2166/* File: armv5te/OP_AGET.S */
2167    /*
2168     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2169     *
2170     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2171     * instructions.  We use a pair of FETCH_Bs instead.
2172     *
2173     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2174     */
2175    /* op vAA, vBB, vCC */
2176    FETCH_B(r2, 1, 0)                   @ r2<- BB
2177    mov     r9, rINST, lsr #8           @ r9<- AA
2178    FETCH_B(r3, 1, 1)                   @ r3<- CC
2179    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2180    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2181    cmp     r0, #0                      @ null array object?
2182    beq     common_errNullObject        @ yes, bail
2183    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2184    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2185    cmp     r1, r3                      @ compare unsigned index, length
2186    bcs     common_errArrayIndex        @ index >= length, bail
2187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2188    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2190    SET_VREG(r2, r9)                    @ vAA<- r2
2191    GOTO_OPCODE(ip)                     @ jump to next instruction
2192
2193
2194/* ------------------------------ */
2195    .balign 64
2196.L_OP_APUT: /* 0x4b */
2197/* File: armv5te/OP_APUT.S */
2198    /*
2199     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2200     *
2201     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2202     * instructions.  We use a pair of FETCH_Bs instead.
2203     *
2204     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2205     */
2206    /* op vAA, vBB, vCC */
2207    FETCH_B(r2, 1, 0)                   @ r2<- BB
2208    mov     r9, rINST, lsr #8           @ r9<- AA
2209    FETCH_B(r3, 1, 1)                   @ r3<- CC
2210    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2211    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2212    cmp     r0, #0                      @ null array object?
2213    beq     common_errNullObject        @ yes, bail
2214    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2215    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2216    cmp     r1, r3                      @ compare unsigned index, length
2217    bcs     common_errArrayIndex        @ index >= length, bail
2218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2219    GET_VREG(r2, r9)                    @ r2<- vAA
2220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2221    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2222    GOTO_OPCODE(ip)                     @ jump to next instruction
2223
2224/* ------------------------------ */
2225    .balign 64
2226.L_OP_APUT_WIDE: /* 0x4c */
2227/* File: armv5te/OP_APUT_WIDE.S */
2228    /*
2229     * Array put, 64 bits.  vBB[vCC] <- vAA.
2230     *
2231     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2232     */
2233    /* aput-wide vAA, vBB, vCC */
2234    FETCH(r0, 1)                        @ r0<- CCBB
2235    mov     r9, rINST, lsr #8           @ r9<- AA
2236    and     r2, r0, #255                @ r2<- BB
2237    mov     r3, r0, lsr #8              @ r3<- CC
2238    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2239    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2240    cmp     r0, #0                      @ null array object?
2241    beq     common_errNullObject        @ yes, bail
2242    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2243    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2244    cmp     r1, r3                      @ compare unsigned index, length
2245    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2246    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2247    b       common_errArrayIndex        @ index >= length, bail
2248    @ May want to swap the order of these two branches depending on how the
2249    @ branch prediction (if any) handles conditional forward branches vs.
2250    @ unconditional forward branches.
2251
2252/* ------------------------------ */
2253    .balign 64
2254.L_OP_APUT_OBJECT: /* 0x4d */
2255/* File: armv5te/OP_APUT_OBJECT.S */
2256    /*
2257     * Store an object into an array.  vBB[vCC] <- vAA.
2258     *
2259     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2260     * instructions.  We use a pair of FETCH_Bs instead.
2261     */
2262    /* op vAA, vBB, vCC */
2263    FETCH(r0, 1)                        @ r0<- CCBB
2264    mov     r9, rINST, lsr #8           @ r9<- AA
2265    and     r2, r0, #255                @ r2<- BB
2266    mov     r3, r0, lsr #8              @ r3<- CC
2267    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2268    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2269    cmp     r1, #0                      @ null array object?
2270    GET_VREG(r9, r9)                    @ r9<- vAA
2271    beq     common_errNullObject        @ yes, bail
2272    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2273    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2274    cmp     r0, r3                      @ compare unsigned index, length
2275    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2276    b       common_errArrayIndex        @ index >= length, bail
2277
2278
2279/* ------------------------------ */
2280    .balign 64
2281.L_OP_APUT_BOOLEAN: /* 0x4e */
2282/* File: armv5te/OP_APUT_BOOLEAN.S */
2283/* File: armv5te/OP_APUT.S */
2284    /*
2285     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2286     *
2287     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2288     * instructions.  We use a pair of FETCH_Bs instead.
2289     *
2290     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2291     */
2292    /* op vAA, vBB, vCC */
2293    FETCH_B(r2, 1, 0)                   @ r2<- BB
2294    mov     r9, rINST, lsr #8           @ r9<- AA
2295    FETCH_B(r3, 1, 1)                   @ r3<- CC
2296    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2297    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2298    cmp     r0, #0                      @ null array object?
2299    beq     common_errNullObject        @ yes, bail
2300    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2301    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2302    cmp     r1, r3                      @ compare unsigned index, length
2303    bcs     common_errArrayIndex        @ index >= length, bail
2304    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2305    GET_VREG(r2, r9)                    @ r2<- vAA
2306    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2307    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2308    GOTO_OPCODE(ip)                     @ jump to next instruction
2309
2310
2311/* ------------------------------ */
2312    .balign 64
2313.L_OP_APUT_BYTE: /* 0x4f */
2314/* File: armv5te/OP_APUT_BYTE.S */
2315/* File: armv5te/OP_APUT.S */
2316    /*
2317     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2318     *
2319     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2320     * instructions.  We use a pair of FETCH_Bs instead.
2321     *
2322     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2323     */
2324    /* op vAA, vBB, vCC */
2325    FETCH_B(r2, 1, 0)                   @ r2<- BB
2326    mov     r9, rINST, lsr #8           @ r9<- AA
2327    FETCH_B(r3, 1, 1)                   @ r3<- CC
2328    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2329    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2330    cmp     r0, #0                      @ null array object?
2331    beq     common_errNullObject        @ yes, bail
2332    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2333    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2334    cmp     r1, r3                      @ compare unsigned index, length
2335    bcs     common_errArrayIndex        @ index >= length, bail
2336    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2337    GET_VREG(r2, r9)                    @ r2<- vAA
2338    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2339    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2340    GOTO_OPCODE(ip)                     @ jump to next instruction
2341
2342
2343/* ------------------------------ */
2344    .balign 64
2345.L_OP_APUT_CHAR: /* 0x50 */
2346/* File: armv5te/OP_APUT_CHAR.S */
2347/* File: armv5te/OP_APUT.S */
2348    /*
2349     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2350     *
2351     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2352     * instructions.  We use a pair of FETCH_Bs instead.
2353     *
2354     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2355     */
2356    /* op vAA, vBB, vCC */
2357    FETCH_B(r2, 1, 0)                   @ r2<- BB
2358    mov     r9, rINST, lsr #8           @ r9<- AA
2359    FETCH_B(r3, 1, 1)                   @ r3<- CC
2360    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2361    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2362    cmp     r0, #0                      @ null array object?
2363    beq     common_errNullObject        @ yes, bail
2364    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2365    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2366    cmp     r1, r3                      @ compare unsigned index, length
2367    bcs     common_errArrayIndex        @ index >= length, bail
2368    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2369    GET_VREG(r2, r9)                    @ r2<- vAA
2370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2371    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2372    GOTO_OPCODE(ip)                     @ jump to next instruction
2373
2374
2375/* ------------------------------ */
2376    .balign 64
2377.L_OP_APUT_SHORT: /* 0x51 */
2378/* File: armv5te/OP_APUT_SHORT.S */
2379/* File: armv5te/OP_APUT.S */
2380    /*
2381     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2382     *
2383     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2384     * instructions.  We use a pair of FETCH_Bs instead.
2385     *
2386     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2387     */
2388    /* op vAA, vBB, vCC */
2389    FETCH_B(r2, 1, 0)                   @ r2<- BB
2390    mov     r9, rINST, lsr #8           @ r9<- AA
2391    FETCH_B(r3, 1, 1)                   @ r3<- CC
2392    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2393    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2394    cmp     r0, #0                      @ null array object?
2395    beq     common_errNullObject        @ yes, bail
2396    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2397    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2398    cmp     r1, r3                      @ compare unsigned index, length
2399    bcs     common_errArrayIndex        @ index >= length, bail
2400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2401    GET_VREG(r2, r9)                    @ r2<- vAA
2402    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2403    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2404    GOTO_OPCODE(ip)                     @ jump to next instruction
2405
2406
2407/* ------------------------------ */
2408    .balign 64
2409.L_OP_IGET: /* 0x52 */
2410/* File: armv6t2/OP_IGET.S */
2411    /*
2412     * General 32-bit instance field get.
2413     *
2414     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2415     */
2416    /* op vA, vB, field@CCCC */
2417    mov     r0, rINST, lsr #12          @ r0<- B
2418    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2419    FETCH(r1, 1)                        @ r1<- field ref CCCC
2420    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2421    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2422    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2423    cmp     r0, #0                      @ is resolved entry null?
2424    bne     .LOP_IGET_finish          @ no, already resolved
24258:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2426    EXPORT_PC()                         @ resolve() could throw
2427    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2428    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2429    cmp     r0, #0
2430    bne     .LOP_IGET_finish
2431    b       common_exceptionThrown
2432
2433/* ------------------------------ */
2434    .balign 64
2435.L_OP_IGET_WIDE: /* 0x53 */
2436/* File: armv6t2/OP_IGET_WIDE.S */
2437    /*
2438     * Wide 32-bit instance field get.
2439     */
2440    /* iget-wide vA, vB, field@CCCC */
2441    mov     r0, rINST, lsr #12          @ r0<- B
2442    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2443    FETCH(r1, 1)                        @ r1<- field ref CCCC
2444    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2445    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2446    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2447    cmp     r0, #0                      @ is resolved entry null?
2448    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24498:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2450    EXPORT_PC()                         @ resolve() could throw
2451    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2452    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2453    cmp     r0, #0
2454    bne     .LOP_IGET_WIDE_finish
2455    b       common_exceptionThrown
2456
2457/* ------------------------------ */
2458    .balign 64
2459.L_OP_IGET_OBJECT: /* 0x54 */
2460/* File: armv5te/OP_IGET_OBJECT.S */
2461/* File: armv5te/OP_IGET.S */
2462    /*
2463     * General 32-bit instance field get.
2464     *
2465     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2466     */
2467    /* op vA, vB, field@CCCC */
2468    mov     r0, rINST, lsr #12          @ r0<- B
2469    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2470    FETCH(r1, 1)                        @ r1<- field ref CCCC
2471    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2472    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2473    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2474    cmp     r0, #0                      @ is resolved entry null?
2475    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24768:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2477    EXPORT_PC()                         @ resolve() could throw
2478    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2479    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2480    cmp     r0, #0
2481    bne     .LOP_IGET_OBJECT_finish
2482    b       common_exceptionThrown
2483
2484
2485/* ------------------------------ */
2486    .balign 64
2487.L_OP_IGET_BOOLEAN: /* 0x55 */
2488/* File: armv5te/OP_IGET_BOOLEAN.S */
2489@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2490/* File: armv5te/OP_IGET.S */
2491    /*
2492     * General 32-bit instance field get.
2493     *
2494     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2495     */
2496    /* op vA, vB, field@CCCC */
2497    mov     r0, rINST, lsr #12          @ r0<- B
2498    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2499    FETCH(r1, 1)                        @ r1<- field ref CCCC
2500    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2501    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2502    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2503    cmp     r0, #0                      @ is resolved entry null?
2504    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25058:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2506    EXPORT_PC()                         @ resolve() could throw
2507    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2508    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2509    cmp     r0, #0
2510    bne     .LOP_IGET_BOOLEAN_finish
2511    b       common_exceptionThrown
2512
2513
2514/* ------------------------------ */
2515    .balign 64
2516.L_OP_IGET_BYTE: /* 0x56 */
2517/* File: armv5te/OP_IGET_BYTE.S */
2518@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2519/* File: armv5te/OP_IGET.S */
2520    /*
2521     * General 32-bit instance field get.
2522     *
2523     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2524     */
2525    /* op vA, vB, field@CCCC */
2526    mov     r0, rINST, lsr #12          @ r0<- B
2527    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2528    FETCH(r1, 1)                        @ r1<- field ref CCCC
2529    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2530    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2531    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2532    cmp     r0, #0                      @ is resolved entry null?
2533    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25348:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2535    EXPORT_PC()                         @ resolve() could throw
2536    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2537    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2538    cmp     r0, #0
2539    bne     .LOP_IGET_BYTE_finish
2540    b       common_exceptionThrown
2541
2542
2543/* ------------------------------ */
2544    .balign 64
2545.L_OP_IGET_CHAR: /* 0x57 */
2546/* File: armv5te/OP_IGET_CHAR.S */
2547@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2548/* File: armv5te/OP_IGET.S */
2549    /*
2550     * General 32-bit instance field get.
2551     *
2552     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2553     */
2554    /* op vA, vB, field@CCCC */
2555    mov     r0, rINST, lsr #12          @ r0<- B
2556    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2557    FETCH(r1, 1)                        @ r1<- field ref CCCC
2558    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2559    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2560    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2561    cmp     r0, #0                      @ is resolved entry null?
2562    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25638:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2564    EXPORT_PC()                         @ resolve() could throw
2565    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2566    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2567    cmp     r0, #0
2568    bne     .LOP_IGET_CHAR_finish
2569    b       common_exceptionThrown
2570
2571
2572/* ------------------------------ */
2573    .balign 64
2574.L_OP_IGET_SHORT: /* 0x58 */
2575/* File: armv5te/OP_IGET_SHORT.S */
2576@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2577/* File: armv5te/OP_IGET.S */
2578    /*
2579     * General 32-bit instance field get.
2580     *
2581     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2582     */
2583    /* op vA, vB, field@CCCC */
2584    mov     r0, rINST, lsr #12          @ r0<- B
2585    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2586    FETCH(r1, 1)                        @ r1<- field ref CCCC
2587    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2588    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2589    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2590    cmp     r0, #0                      @ is resolved entry null?
2591    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25928:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2593    EXPORT_PC()                         @ resolve() could throw
2594    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2595    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2596    cmp     r0, #0
2597    bne     .LOP_IGET_SHORT_finish
2598    b       common_exceptionThrown
2599
2600
2601/* ------------------------------ */
2602    .balign 64
2603.L_OP_IPUT: /* 0x59 */
2604/* File: armv6t2/OP_IPUT.S */
2605    /*
2606     * General 32-bit instance field put.
2607     *
2608     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2609     */
2610    /* op vA, vB, field@CCCC */
2611    mov     r0, rINST, lsr #12          @ r0<- B
2612    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2613    FETCH(r1, 1)                        @ r1<- field ref CCCC
2614    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2615    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2616    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2617    cmp     r0, #0                      @ is resolved entry null?
2618    bne     .LOP_IPUT_finish          @ no, already resolved
26198:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2620    EXPORT_PC()                         @ resolve() could throw
2621    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2622    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2623    cmp     r0, #0                      @ success?
2624    bne     .LOP_IPUT_finish          @ yes, finish up
2625    b       common_exceptionThrown
2626
2627/* ------------------------------ */
2628    .balign 64
2629.L_OP_IPUT_WIDE: /* 0x5a */
2630/* File: armv6t2/OP_IPUT_WIDE.S */
2631    /* iput-wide vA, vB, field@CCCC */
2632    mov     r0, rINST, lsr #12          @ r0<- B
2633    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2634    FETCH(r1, 1)                        @ r1<- field ref CCCC
2635    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2636    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2637    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2638    cmp     r0, #0                      @ is resolved entry null?
2639    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26408:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2641    EXPORT_PC()                         @ resolve() could throw
2642    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2643    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2644    cmp     r0, #0                      @ success?
2645    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2646    b       common_exceptionThrown
2647
2648/* ------------------------------ */
2649    .balign 64
2650.L_OP_IPUT_OBJECT: /* 0x5b */
2651/* File: armv5te/OP_IPUT_OBJECT.S */
2652    /*
2653     * 32-bit instance field put.
2654     *
2655     * for: iput-object, iput-object-volatile
2656     */
2657    /* op vA, vB, field@CCCC */
2658    mov     r0, rINST, lsr #12          @ r0<- B
2659    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2660    FETCH(r1, 1)                        @ r1<- field ref CCCC
2661    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2662    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2663    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2664    cmp     r0, #0                      @ is resolved entry null?
2665    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26668:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2667    EXPORT_PC()                         @ resolve() could throw
2668    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2669    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2670    cmp     r0, #0                      @ success?
2671    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2672    b       common_exceptionThrown
2673
2674/* ------------------------------ */
2675    .balign 64
2676.L_OP_IPUT_BOOLEAN: /* 0x5c */
2677/* File: armv5te/OP_IPUT_BOOLEAN.S */
2678@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2679/* File: armv5te/OP_IPUT.S */
2680    /*
2681     * General 32-bit instance field put.
2682     *
2683     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2684     */
2685    /* op vA, vB, field@CCCC */
2686    mov     r0, rINST, lsr #12          @ r0<- B
2687    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2688    FETCH(r1, 1)                        @ r1<- field ref CCCC
2689    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2690    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2691    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2692    cmp     r0, #0                      @ is resolved entry null?
2693    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2695    EXPORT_PC()                         @ resolve() could throw
2696    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2697    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2698    cmp     r0, #0                      @ success?
2699    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2700    b       common_exceptionThrown
2701
2702
2703/* ------------------------------ */
2704    .balign 64
2705.L_OP_IPUT_BYTE: /* 0x5d */
2706/* File: armv5te/OP_IPUT_BYTE.S */
2707@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2708/* File: armv5te/OP_IPUT.S */
2709    /*
2710     * General 32-bit instance field put.
2711     *
2712     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2713     */
2714    /* op vA, vB, field@CCCC */
2715    mov     r0, rINST, lsr #12          @ r0<- B
2716    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2717    FETCH(r1, 1)                        @ r1<- field ref CCCC
2718    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2719    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2720    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2721    cmp     r0, #0                      @ is resolved entry null?
2722    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27238:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2724    EXPORT_PC()                         @ resolve() could throw
2725    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2726    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2727    cmp     r0, #0                      @ success?
2728    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2729    b       common_exceptionThrown
2730
2731
2732/* ------------------------------ */
2733    .balign 64
2734.L_OP_IPUT_CHAR: /* 0x5e */
2735/* File: armv5te/OP_IPUT_CHAR.S */
2736@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2737/* File: armv5te/OP_IPUT.S */
2738    /*
2739     * General 32-bit instance field put.
2740     *
2741     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2742     */
2743    /* op vA, vB, field@CCCC */
2744    mov     r0, rINST, lsr #12          @ r0<- B
2745    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2746    FETCH(r1, 1)                        @ r1<- field ref CCCC
2747    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2748    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2749    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2750    cmp     r0, #0                      @ is resolved entry null?
2751    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27528:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2753    EXPORT_PC()                         @ resolve() could throw
2754    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2755    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2756    cmp     r0, #0                      @ success?
2757    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2758    b       common_exceptionThrown
2759
2760
2761/* ------------------------------ */
2762    .balign 64
2763.L_OP_IPUT_SHORT: /* 0x5f */
2764/* File: armv5te/OP_IPUT_SHORT.S */
2765@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2766/* File: armv5te/OP_IPUT.S */
2767    /*
2768     * General 32-bit instance field put.
2769     *
2770     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2771     */
2772    /* op vA, vB, field@CCCC */
2773    mov     r0, rINST, lsr #12          @ r0<- B
2774    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2775    FETCH(r1, 1)                        @ r1<- field ref CCCC
2776    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2777    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2778    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2779    cmp     r0, #0                      @ is resolved entry null?
2780    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27818:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2782    EXPORT_PC()                         @ resolve() could throw
2783    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2784    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2785    cmp     r0, #0                      @ success?
2786    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2787    b       common_exceptionThrown
2788
2789
2790/* ------------------------------ */
2791    .balign 64
2792.L_OP_SGET: /* 0x60 */
2793/* File: armv5te/OP_SGET.S */
2794    /*
2795     * General 32-bit SGET handler.
2796     *
2797     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2798     */
2799    /* op vAA, field@BBBB */
2800    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2801    FETCH(r1, 1)                        @ r1<- field ref BBBB
2802    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2803    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2804    cmp     r0, #0                      @ is resolved entry null?
2805    beq     .LOP_SGET_resolve         @ yes, do resolve
2806.LOP_SGET_finish: @ field ptr in r0
2807    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2808    @ no-op                             @ acquiring load
2809    mov     r2, rINST, lsr #8           @ r2<- AA
2810    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2811    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2813    GOTO_OPCODE(ip)                     @ jump to next instruction
2814
2815/* ------------------------------ */
2816    .balign 64
2817.L_OP_SGET_WIDE: /* 0x61 */
2818/* File: armv5te/OP_SGET_WIDE.S */
2819    /*
2820     * 64-bit SGET handler.
2821     */
2822    /* sget-wide vAA, field@BBBB */
2823    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2824    FETCH(r1, 1)                        @ r1<- field ref BBBB
2825    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2826    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2827    cmp     r0, #0                      @ is resolved entry null?
2828    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2829.LOP_SGET_WIDE_finish:
2830    mov     r9, rINST, lsr #8           @ r9<- AA
2831    .if 0
2832    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2833    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2834    .else
2835    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2836    .endif
2837    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2839    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2841    GOTO_OPCODE(ip)                     @ jump to next instruction
2842
2843/* ------------------------------ */
2844    .balign 64
2845.L_OP_SGET_OBJECT: /* 0x62 */
2846/* File: armv5te/OP_SGET_OBJECT.S */
2847/* File: armv5te/OP_SGET.S */
2848    /*
2849     * General 32-bit SGET handler.
2850     *
2851     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2852     */
2853    /* op vAA, field@BBBB */
2854    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2855    FETCH(r1, 1)                        @ r1<- field ref BBBB
2856    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858    cmp     r0, #0                      @ is resolved entry null?
2859    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2860.LOP_SGET_OBJECT_finish: @ field ptr in r0
2861    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2862    @ no-op                             @ acquiring load
2863    mov     r2, rINST, lsr #8           @ r2<- AA
2864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867    GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869
2870/* ------------------------------ */
2871    .balign 64
2872.L_OP_SGET_BOOLEAN: /* 0x63 */
2873/* File: armv5te/OP_SGET_BOOLEAN.S */
2874/* File: armv5te/OP_SGET.S */
2875    /*
2876     * General 32-bit SGET handler.
2877     *
2878     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2879     */
2880    /* op vAA, field@BBBB */
2881    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2882    FETCH(r1, 1)                        @ r1<- field ref BBBB
2883    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2885    cmp     r0, #0                      @ is resolved entry null?
2886    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2887.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2888    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2889    @ no-op                             @ acquiring load
2890    mov     r2, rINST, lsr #8           @ r2<- AA
2891    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2892    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2894    GOTO_OPCODE(ip)                     @ jump to next instruction
2895
2896
2897/* ------------------------------ */
2898    .balign 64
2899.L_OP_SGET_BYTE: /* 0x64 */
2900/* File: armv5te/OP_SGET_BYTE.S */
2901/* File: armv5te/OP_SGET.S */
2902    /*
2903     * General 32-bit SGET handler.
2904     *
2905     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2906     */
2907    /* op vAA, field@BBBB */
2908    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2909    FETCH(r1, 1)                        @ r1<- field ref BBBB
2910    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2911    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2912    cmp     r0, #0                      @ is resolved entry null?
2913    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2914.LOP_SGET_BYTE_finish: @ field ptr in r0
2915    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2916    @ no-op                             @ acquiring load
2917    mov     r2, rINST, lsr #8           @ r2<- AA
2918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2919    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2921    GOTO_OPCODE(ip)                     @ jump to next instruction
2922
2923
2924/* ------------------------------ */
2925    .balign 64
2926.L_OP_SGET_CHAR: /* 0x65 */
2927/* File: armv5te/OP_SGET_CHAR.S */
2928/* File: armv5te/OP_SGET.S */
2929    /*
2930     * General 32-bit SGET handler.
2931     *
2932     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2933     */
2934    /* op vAA, field@BBBB */
2935    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2936    FETCH(r1, 1)                        @ r1<- field ref BBBB
2937    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2939    cmp     r0, #0                      @ is resolved entry null?
2940    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2941.LOP_SGET_CHAR_finish: @ field ptr in r0
2942    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2943    @ no-op                             @ acquiring load
2944    mov     r2, rINST, lsr #8           @ r2<- AA
2945    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948    GOTO_OPCODE(ip)                     @ jump to next instruction
2949
2950
2951/* ------------------------------ */
2952    .balign 64
2953.L_OP_SGET_SHORT: /* 0x66 */
2954/* File: armv5te/OP_SGET_SHORT.S */
2955/* File: armv5te/OP_SGET.S */
2956    /*
2957     * General 32-bit SGET handler.
2958     *
2959     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2960     */
2961    /* op vAA, field@BBBB */
2962    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2963    FETCH(r1, 1)                        @ r1<- field ref BBBB
2964    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2965    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2966    cmp     r0, #0                      @ is resolved entry null?
2967    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2968.LOP_SGET_SHORT_finish: @ field ptr in r0
2969    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2970    @ no-op                             @ acquiring load
2971    mov     r2, rINST, lsr #8           @ r2<- AA
2972    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2973    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2974    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2975    GOTO_OPCODE(ip)                     @ jump to next instruction
2976
2977
2978/* ------------------------------ */
2979    .balign 64
2980.L_OP_SPUT: /* 0x67 */
2981/* File: armv5te/OP_SPUT.S */
2982    /*
2983     * General 32-bit SPUT handler.
2984     *
2985     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2986     */
2987    /* op vAA, field@BBBB */
2988    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2989    FETCH(r1, 1)                        @ r1<- field ref BBBB
2990    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2991    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2992    cmp     r0, #0                      @ is resolved entry null?
2993    beq     .LOP_SPUT_resolve         @ yes, do resolve
2994.LOP_SPUT_finish:   @ field ptr in r0
2995    mov     r2, rINST, lsr #8           @ r2<- AA
2996    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2997    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2999    @ no-op                             @ releasing store
3000    str     r1, [r0, #offStaticField_value] @ field<- vAA
3001    GOTO_OPCODE(ip)                     @ jump to next instruction
3002
3003/* ------------------------------ */
3004    .balign 64
3005.L_OP_SPUT_WIDE: /* 0x68 */
3006/* File: armv5te/OP_SPUT_WIDE.S */
3007    /*
3008     * 64-bit SPUT handler.
3009     */
3010    /* sput-wide vAA, field@BBBB */
3011    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3012    FETCH(r1, 1)                        @ r1<- field ref BBBB
3013    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3014    mov     r9, rINST, lsr #8           @ r9<- AA
3015    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3016    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3017    cmp     r2, #0                      @ is resolved entry null?
3018    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3019.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3020    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3021    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3022    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3023    .if 0
3024    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3025    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3026    .else
3027    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3028    .endif
3029    GOTO_OPCODE(r10)                    @ jump to next instruction
3030
3031/* ------------------------------ */
3032    .balign 64
3033.L_OP_SPUT_OBJECT: /* 0x69 */
3034/* File: armv5te/OP_SPUT_OBJECT.S */
3035    /*
3036     * 32-bit SPUT handler for objects
3037     *
3038     * for: sput-object, sput-object-volatile
3039     */
3040    /* op vAA, field@BBBB */
3041    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3042    FETCH(r1, 1)                        @ r1<- field ref BBBB
3043    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3044    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3045    cmp     r0, #0                      @ is resolved entry null?
3046    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3047    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
3048    EXPORT_PC()                         @ resolve() could throw, so export now
3049    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
3050    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3051    cmp     r0, #0                      @ success?
3052    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3053    b       common_exceptionThrown      @ no, handle exception
3054
3055
3056/* ------------------------------ */
3057    .balign 64
3058.L_OP_SPUT_BOOLEAN: /* 0x6a */
3059/* File: armv5te/OP_SPUT_BOOLEAN.S */
3060/* File: armv5te/OP_SPUT.S */
3061    /*
3062     * General 32-bit SPUT handler.
3063     *
3064     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3065     */
3066    /* op vAA, field@BBBB */
3067    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3068    FETCH(r1, 1)                        @ r1<- field ref BBBB
3069    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3070    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3071    cmp     r0, #0                      @ is resolved entry null?
3072    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3073.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3074    mov     r2, rINST, lsr #8           @ r2<- AA
3075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3076    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3078    @ no-op                             @ releasing store
3079    str     r1, [r0, #offStaticField_value] @ field<- vAA
3080    GOTO_OPCODE(ip)                     @ jump to next instruction
3081
3082
3083/* ------------------------------ */
3084    .balign 64
3085.L_OP_SPUT_BYTE: /* 0x6b */
3086/* File: armv5te/OP_SPUT_BYTE.S */
3087/* File: armv5te/OP_SPUT.S */
3088    /*
3089     * General 32-bit SPUT handler.
3090     *
3091     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3092     */
3093    /* op vAA, field@BBBB */
3094    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3095    FETCH(r1, 1)                        @ r1<- field ref BBBB
3096    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3097    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3098    cmp     r0, #0                      @ is resolved entry null?
3099    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3100.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3101    mov     r2, rINST, lsr #8           @ r2<- AA
3102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3103    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3105    @ no-op                             @ releasing store
3106    str     r1, [r0, #offStaticField_value] @ field<- vAA
3107    GOTO_OPCODE(ip)                     @ jump to next instruction
3108
3109
3110/* ------------------------------ */
3111    .balign 64
3112.L_OP_SPUT_CHAR: /* 0x6c */
3113/* File: armv5te/OP_SPUT_CHAR.S */
3114/* File: armv5te/OP_SPUT.S */
3115    /*
3116     * General 32-bit SPUT handler.
3117     *
3118     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3119     */
3120    /* op vAA, field@BBBB */
3121    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3122    FETCH(r1, 1)                        @ r1<- field ref BBBB
3123    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3124    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3125    cmp     r0, #0                      @ is resolved entry null?
3126    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3127.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3128    mov     r2, rINST, lsr #8           @ r2<- AA
3129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3130    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3131    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3132    @ no-op                             @ releasing store
3133    str     r1, [r0, #offStaticField_value] @ field<- vAA
3134    GOTO_OPCODE(ip)                     @ jump to next instruction
3135
3136
3137/* ------------------------------ */
3138    .balign 64
3139.L_OP_SPUT_SHORT: /* 0x6d */
3140/* File: armv5te/OP_SPUT_SHORT.S */
3141/* File: armv5te/OP_SPUT.S */
3142    /*
3143     * General 32-bit SPUT handler.
3144     *
3145     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3146     */
3147    /* op vAA, field@BBBB */
3148    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3149    FETCH(r1, 1)                        @ r1<- field ref BBBB
3150    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3151    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3152    cmp     r0, #0                      @ is resolved entry null?
3153    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3154.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3155    mov     r2, rINST, lsr #8           @ r2<- AA
3156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3157    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3159    @ no-op                             @ releasing store
3160    str     r1, [r0, #offStaticField_value] @ field<- vAA
3161    GOTO_OPCODE(ip)                     @ jump to next instruction
3162
3163
3164/* ------------------------------ */
3165    .balign 64
3166.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3167/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3168    /*
3169     * Handle a virtual method call.
3170     *
3171     * for: invoke-virtual, invoke-virtual/range
3172     */
3173    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3174    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3175    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3176    FETCH(r1, 1)                        @ r1<- BBBB
3177    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3178    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3179    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3180    .if     (!0)
3181    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3182    .endif
3183    cmp     r0, #0                      @ already resolved?
3184    EXPORT_PC()                         @ must export for invoke
3185    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3186    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3187    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3188    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3189    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3190    cmp     r0, #0                      @ got null?
3191    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3192    b       common_exceptionThrown      @ yes, handle exception
3193
3194/* ------------------------------ */
3195    .balign 64
3196.L_OP_INVOKE_SUPER: /* 0x6f */
3197/* File: armv5te/OP_INVOKE_SUPER.S */
3198    /*
3199     * Handle a "super" method call.
3200     *
3201     * for: invoke-super, invoke-super/range
3202     */
3203    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3204    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3205    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3206    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3207    .if     (!0)
3208    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3209    .endif
3210    FETCH(r1, 1)                        @ r1<- BBBB
3211    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3212    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3213    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3214    cmp     r2, #0                      @ null "this"?
3215    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3216    beq     common_errNullObject        @ null "this", throw exception
3217    cmp     r0, #0                      @ already resolved?
3218    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3219    EXPORT_PC()                         @ must export for invoke
3220    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3221    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3222
3223/* ------------------------------ */
3224    .balign 64
3225.L_OP_INVOKE_DIRECT: /* 0x70 */
3226/* File: armv5te/OP_INVOKE_DIRECT.S */
3227    /*
3228     * Handle a direct method call.
3229     *
3230     * (We could defer the "is 'this' pointer null" test to the common
3231     * method invocation code, and use a flag to indicate that static
3232     * calls don't count.  If we do this as part of copying the arguments
3233     * out we could avoiding loading the first arg twice.)
3234     *
3235     * for: invoke-direct, invoke-direct/range
3236     */
3237    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3238    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3239    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3240    FETCH(r1, 1)                        @ r1<- BBBB
3241    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3242    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3243    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3244    .if     (!0)
3245    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3246    .endif
3247    cmp     r0, #0                      @ already resolved?
3248    EXPORT_PC()                         @ must export for invoke
3249    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3250    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3251.LOP_INVOKE_DIRECT_finish:
3252    cmp     r2, #0                      @ null "this" ref?
3253    bne     common_invokeMethodNoRange   @ no, continue on
3254    b       common_errNullObject        @ yes, throw exception
3255
3256/* ------------------------------ */
3257    .balign 64
3258.L_OP_INVOKE_STATIC: /* 0x71 */
3259/* File: armv5te/OP_INVOKE_STATIC.S */
3260    /*
3261     * Handle a static method call.
3262     *
3263     * for: invoke-static, invoke-static/range
3264     */
3265    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3266    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3267    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3268    FETCH(r1, 1)                        @ r1<- BBBB
3269    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3270    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3271    cmp     r0, #0                      @ already resolved?
3272    EXPORT_PC()                         @ must export for invoke
3273    bne     common_invokeMethodNoRange @ yes, continue on
32740:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3275    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3276    mov     r2, #METHOD_STATIC          @ resolver method type
3277    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3278    cmp     r0, #0                      @ got null?
3279    bne     common_invokeMethodNoRange @ no, continue
3280    b       common_exceptionThrown      @ yes, handle exception
3281
3282/* ------------------------------ */
3283    .balign 64
3284.L_OP_INVOKE_INTERFACE: /* 0x72 */
3285/* File: armv5te/OP_INVOKE_INTERFACE.S */
3286    /*
3287     * Handle an interface method call.
3288     *
3289     * for: invoke-interface, invoke-interface/range
3290     */
3291    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3292    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3293    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3294    FETCH(r1, 1)                        @ r1<- BBBB
3295    .if     (!0)
3296    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3297    .endif
3298    EXPORT_PC()                         @ must export for invoke
3299    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3300    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3301    cmp     r0, #0                      @ null obj?
3302    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3303    beq     common_errNullObject        @ yes, fail
3304    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3305    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3306    cmp     r0, #0                      @ failed?
3307    beq     common_exceptionThrown      @ yes, handle exception
3308    b       common_invokeMethodNoRange @ jump to common handler
3309
3310/* ------------------------------ */
3311    .balign 64
3312.L_OP_UNUSED_73: /* 0x73 */
3313/* File: armv5te/OP_UNUSED_73.S */
3314/* File: armv5te/unused.S */
3315    bl      common_abort
3316
3317
3318/* ------------------------------ */
3319    .balign 64
3320.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3321/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3322/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3323    /*
3324     * Handle a virtual method call.
3325     *
3326     * for: invoke-virtual, invoke-virtual/range
3327     */
3328    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3329    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3330    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3331    FETCH(r1, 1)                        @ r1<- BBBB
3332    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3333    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3334    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3335    .if     (!1)
3336    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3337    .endif
3338    cmp     r0, #0                      @ already resolved?
3339    EXPORT_PC()                         @ must export for invoke
3340    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3341    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3342    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3343    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3344    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3345    cmp     r0, #0                      @ got null?
3346    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3347    b       common_exceptionThrown      @ yes, handle exception
3348
3349
3350/* ------------------------------ */
3351    .balign 64
3352.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3353/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3354/* File: armv5te/OP_INVOKE_SUPER.S */
3355    /*
3356     * Handle a "super" method call.
3357     *
3358     * for: invoke-super, invoke-super/range
3359     */
3360    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3361    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3362    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3363    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3364    .if     (!1)
3365    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3366    .endif
3367    FETCH(r1, 1)                        @ r1<- BBBB
3368    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3369    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3370    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3371    cmp     r2, #0                      @ null "this"?
3372    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3373    beq     common_errNullObject        @ null "this", throw exception
3374    cmp     r0, #0                      @ already resolved?
3375    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3376    EXPORT_PC()                         @ must export for invoke
3377    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3378    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3379
3380
3381/* ------------------------------ */
3382    .balign 64
3383.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3384/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3385/* File: armv5te/OP_INVOKE_DIRECT.S */
3386    /*
3387     * Handle a direct method call.
3388     *
3389     * (We could defer the "is 'this' pointer null" test to the common
3390     * method invocation code, and use a flag to indicate that static
3391     * calls don't count.  If we do this as part of copying the arguments
3392     * out we could avoiding loading the first arg twice.)
3393     *
3394     * for: invoke-direct, invoke-direct/range
3395     */
3396    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3397    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3398    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3399    FETCH(r1, 1)                        @ r1<- BBBB
3400    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3401    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3402    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3403    .if     (!1)
3404    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3405    .endif
3406    cmp     r0, #0                      @ already resolved?
3407    EXPORT_PC()                         @ must export for invoke
3408    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3409    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3410.LOP_INVOKE_DIRECT_RANGE_finish:
3411    cmp     r2, #0                      @ null "this" ref?
3412    bne     common_invokeMethodRange   @ no, continue on
3413    b       common_errNullObject        @ yes, throw exception
3414
3415
3416/* ------------------------------ */
3417    .balign 64
3418.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3419/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3420/* File: armv5te/OP_INVOKE_STATIC.S */
3421    /*
3422     * Handle a static method call.
3423     *
3424     * for: invoke-static, invoke-static/range
3425     */
3426    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3427    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3428    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3429    FETCH(r1, 1)                        @ r1<- BBBB
3430    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3431    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3432    cmp     r0, #0                      @ already resolved?
3433    EXPORT_PC()                         @ must export for invoke
3434    bne     common_invokeMethodRange @ yes, continue on
34350:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3436    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3437    mov     r2, #METHOD_STATIC          @ resolver method type
3438    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3439    cmp     r0, #0                      @ got null?
3440    bne     common_invokeMethodRange @ no, continue
3441    b       common_exceptionThrown      @ yes, handle exception
3442
3443
3444/* ------------------------------ */
3445    .balign 64
3446.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3447/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3448/* File: armv5te/OP_INVOKE_INTERFACE.S */
3449    /*
3450     * Handle an interface method call.
3451     *
3452     * for: invoke-interface, invoke-interface/range
3453     */
3454    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3455    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3456    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3457    FETCH(r1, 1)                        @ r1<- BBBB
3458    .if     (!1)
3459    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3460    .endif
3461    EXPORT_PC()                         @ must export for invoke
3462    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3463    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3464    cmp     r0, #0                      @ null obj?
3465    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3466    beq     common_errNullObject        @ yes, fail
3467    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3468    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3469    cmp     r0, #0                      @ failed?
3470    beq     common_exceptionThrown      @ yes, handle exception
3471    b       common_invokeMethodRange @ jump to common handler
3472
3473
3474/* ------------------------------ */
3475    .balign 64
3476.L_OP_UNUSED_79: /* 0x79 */
3477/* File: armv5te/OP_UNUSED_79.S */
3478/* File: armv5te/unused.S */
3479    bl      common_abort
3480
3481
3482/* ------------------------------ */
3483    .balign 64
3484.L_OP_UNUSED_7A: /* 0x7a */
3485/* File: armv5te/OP_UNUSED_7A.S */
3486/* File: armv5te/unused.S */
3487    bl      common_abort
3488
3489
3490/* ------------------------------ */
3491    .balign 64
3492.L_OP_NEG_INT: /* 0x7b */
3493/* File: armv6t2/OP_NEG_INT.S */
3494/* File: armv6t2/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    ubfx    r9, rINST, #8, #4           @ r9<- A
3506    GET_VREG(r0, r3)                    @ r0<- vB
3507                               @ optional op; may set condition codes
3508    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3509    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3510    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3511    SET_VREG(r0, r9)                    @ vAA<- r0
3512    GOTO_OPCODE(ip)                     @ jump to next instruction
3513    /* 8-9 instructions */
3514
3515
3516/* ------------------------------ */
3517    .balign 64
3518.L_OP_NOT_INT: /* 0x7c */
3519/* File: armv6t2/OP_NOT_INT.S */
3520/* File: armv6t2/unop.S */
3521    /*
3522     * Generic 32-bit unary operation.  Provide an "instr" line that
3523     * specifies an instruction that performs "result = op r0".
3524     * This could be an ARM instruction or a function call.
3525     *
3526     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3527     *      int-to-byte, int-to-char, int-to-short
3528     */
3529    /* unop vA, vB */
3530    mov     r3, rINST, lsr #12          @ r3<- B
3531    ubfx    r9, rINST, #8, #4           @ r9<- A
3532    GET_VREG(r0, r3)                    @ r0<- vB
3533                               @ optional op; may set condition codes
3534    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3535    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3537    SET_VREG(r0, r9)                    @ vAA<- r0
3538    GOTO_OPCODE(ip)                     @ jump to next instruction
3539    /* 8-9 instructions */
3540
3541
3542/* ------------------------------ */
3543    .balign 64
3544.L_OP_NEG_LONG: /* 0x7d */
3545/* File: armv6t2/OP_NEG_LONG.S */
3546/* File: armv6t2/unopWide.S */
3547    /*
3548     * Generic 64-bit unary operation.  Provide an "instr" line that
3549     * specifies an instruction that performs "result = op r0/r1".
3550     * This could be an ARM instruction or a function call.
3551     *
3552     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3553     */
3554    /* unop vA, vB */
3555    mov     r3, rINST, lsr #12          @ r3<- B
3556    ubfx    r9, rINST, #8, #4           @ r9<- A
3557    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3558    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3559    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3560    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3561    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3562    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3564    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3565    GOTO_OPCODE(ip)                     @ jump to next instruction
3566    /* 10-11 instructions */
3567
3568
3569/* ------------------------------ */
3570    .balign 64
3571.L_OP_NOT_LONG: /* 0x7e */
3572/* File: armv6t2/OP_NOT_LONG.S */
3573/* File: armv6t2/unopWide.S */
3574    /*
3575     * Generic 64-bit unary operation.  Provide an "instr" line that
3576     * specifies an instruction that performs "result = op r0/r1".
3577     * This could be an ARM instruction or a function call.
3578     *
3579     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3580     */
3581    /* unop vA, vB */
3582    mov     r3, rINST, lsr #12          @ r3<- B
3583    ubfx    r9, rINST, #8, #4           @ r9<- A
3584    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3585    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3586    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3587    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3588    mvn     r0, r0                           @ optional op; may set condition codes
3589    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3591    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3592    GOTO_OPCODE(ip)                     @ jump to next instruction
3593    /* 10-11 instructions */
3594
3595
3596/* ------------------------------ */
3597    .balign 64
3598.L_OP_NEG_FLOAT: /* 0x7f */
3599/* File: armv6t2/OP_NEG_FLOAT.S */
3600/* File: armv6t2/unop.S */
3601    /*
3602     * Generic 32-bit unary operation.  Provide an "instr" line that
3603     * specifies an instruction that performs "result = op r0".
3604     * This could be an ARM instruction or a function call.
3605     *
3606     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3607     *      int-to-byte, int-to-char, int-to-short
3608     */
3609    /* unop vA, vB */
3610    mov     r3, rINST, lsr #12          @ r3<- B
3611    ubfx    r9, rINST, #8, #4           @ r9<- A
3612    GET_VREG(r0, r3)                    @ r0<- vB
3613                               @ optional op; may set condition codes
3614    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3615    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3617    SET_VREG(r0, r9)                    @ vAA<- r0
3618    GOTO_OPCODE(ip)                     @ jump to next instruction
3619    /* 8-9 instructions */
3620
3621
3622/* ------------------------------ */
3623    .balign 64
3624.L_OP_NEG_DOUBLE: /* 0x80 */
3625/* File: armv6t2/OP_NEG_DOUBLE.S */
3626/* File: armv6t2/unopWide.S */
3627    /*
3628     * Generic 64-bit unary operation.  Provide an "instr" line that
3629     * specifies an instruction that performs "result = op r0/r1".
3630     * This could be an ARM instruction or a function call.
3631     *
3632     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3633     */
3634    /* unop vA, vB */
3635    mov     r3, rINST, lsr #12          @ r3<- B
3636    ubfx    r9, rINST, #8, #4           @ r9<- A
3637    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3638    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3639    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3640    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3641                               @ optional op; may set condition codes
3642    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3643    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3644    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3645    GOTO_OPCODE(ip)                     @ jump to next instruction
3646    /* 10-11 instructions */
3647
3648
3649/* ------------------------------ */
3650    .balign 64
3651.L_OP_INT_TO_LONG: /* 0x81 */
3652/* File: armv6t2/OP_INT_TO_LONG.S */
3653/* File: armv6t2/unopWider.S */
3654    /*
3655     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3656     * that specifies an instruction that performs "result = op r0", where
3657     * "result" is a 64-bit quantity in r0/r1.
3658     *
3659     * For: int-to-long, int-to-double, float-to-long, float-to-double
3660     */
3661    /* unop vA, vB */
3662    mov     r3, rINST, lsr #12          @ r3<- B
3663    ubfx    r9, rINST, #8, #4           @ r9<- A
3664    GET_VREG(r0, r3)                    @ r0<- vB
3665    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3666                               @ optional op; may set condition codes
3667    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3668    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3669    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3670    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3671    GOTO_OPCODE(ip)                     @ jump to next instruction
3672    /* 9-10 instructions */
3673
3674
3675/* ------------------------------ */
3676    .balign 64
3677.L_OP_INT_TO_FLOAT: /* 0x82 */
3678/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3679/* File: arm-vfp/funop.S */
3680    /*
3681     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3682     * line that specifies an instruction that performs "s1 = op s0".
3683     *
3684     * for: int-to-float, float-to-int
3685     */
3686    /* unop vA, vB */
3687    mov     r3, rINST, lsr #12          @ r3<- B
3688    mov     r9, rINST, lsr #8           @ r9<- A+
3689    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3690    flds    s0, [r3]                    @ s0<- vB
3691    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3692    and     r9, r9, #15                 @ r9<- A
3693    fsitos  s1, s0                              @ s1<- op
3694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3695    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3696    fsts    s1, [r9]                    @ vA<- s1
3697    GOTO_OPCODE(ip)                     @ jump to next instruction
3698
3699
3700/* ------------------------------ */
3701    .balign 64
3702.L_OP_INT_TO_DOUBLE: /* 0x83 */
3703/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3704/* File: arm-vfp/funopWider.S */
3705    /*
3706     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3707     * "instr" line that specifies an instruction that performs "d0 = op s0".
3708     *
3709     * For: int-to-double, float-to-double
3710     */
3711    /* unop vA, vB */
3712    mov     r3, rINST, lsr #12          @ r3<- B
3713    mov     r9, rINST, lsr #8           @ r9<- A+
3714    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3715    flds    s0, [r3]                    @ s0<- vB
3716    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3717    and     r9, r9, #15                 @ r9<- A
3718    fsitod  d0, s0                              @ d0<- op
3719    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3720    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3721    fstd    d0, [r9]                    @ vA<- d0
3722    GOTO_OPCODE(ip)                     @ jump to next instruction
3723
3724
3725/* ------------------------------ */
3726    .balign 64
3727.L_OP_LONG_TO_INT: /* 0x84 */
3728/* File: armv5te/OP_LONG_TO_INT.S */
3729/* we ignore the high word, making this equivalent to a 32-bit reg move */
3730/* File: armv5te/OP_MOVE.S */
3731    /* for move, move-object, long-to-int */
3732    /* op vA, vB */
3733    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3734    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3735    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3736    GET_VREG(r2, r1)                    @ r2<- fp[B]
3737    and     r0, r0, #15
3738    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3739    SET_VREG(r2, r0)                    @ fp[A]<- r2
3740    GOTO_OPCODE(ip)                     @ execute next instruction
3741
3742
3743/* ------------------------------ */
3744    .balign 64
3745.L_OP_LONG_TO_FLOAT: /* 0x85 */
3746/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3747/* File: armv6t2/unopNarrower.S */
3748    /*
3749     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3750     * that specifies an instruction that performs "result = op r0/r1", where
3751     * "result" is a 32-bit quantity in r0.
3752     *
3753     * For: long-to-float, double-to-int, double-to-float
3754     *
3755     * (This would work for long-to-int, but that instruction is actually
3756     * an exact match for OP_MOVE.)
3757     */
3758    /* unop vA, vB */
3759    mov     r3, rINST, lsr #12          @ r3<- B
3760    ubfx    r9, rINST, #8, #4           @ r9<- A
3761    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3762    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3763    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3764                               @ optional op; may set condition codes
3765    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3766    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3767    SET_VREG(r0, r9)                    @ vA<- r0
3768    GOTO_OPCODE(ip)                     @ jump to next instruction
3769    /* 9-10 instructions */
3770
3771
3772/* ------------------------------ */
3773    .balign 64
3774.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3775/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3776/* File: armv6t2/unopWide.S */
3777    /*
3778     * Generic 64-bit unary operation.  Provide an "instr" line that
3779     * specifies an instruction that performs "result = op r0/r1".
3780     * This could be an ARM instruction or a function call.
3781     *
3782     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3783     */
3784    /* unop vA, vB */
3785    mov     r3, rINST, lsr #12          @ r3<- B
3786    ubfx    r9, rINST, #8, #4           @ r9<- A
3787    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3788    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3789    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3790    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3791                               @ optional op; may set condition codes
3792    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3793    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3794    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3795    GOTO_OPCODE(ip)                     @ jump to next instruction
3796    /* 10-11 instructions */
3797
3798
3799/* ------------------------------ */
3800    .balign 64
3801.L_OP_FLOAT_TO_INT: /* 0x87 */
3802/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3803/* File: arm-vfp/funop.S */
3804    /*
3805     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3806     * line that specifies an instruction that performs "s1 = op s0".
3807     *
3808     * for: int-to-float, float-to-int
3809     */
3810    /* unop vA, vB */
3811    mov     r3, rINST, lsr #12          @ r3<- B
3812    mov     r9, rINST, lsr #8           @ r9<- A+
3813    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3814    flds    s0, [r3]                    @ s0<- vB
3815    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3816    and     r9, r9, #15                 @ r9<- A
3817    ftosizs s1, s0                              @ s1<- op
3818    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3819    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3820    fsts    s1, [r9]                    @ vA<- s1
3821    GOTO_OPCODE(ip)                     @ jump to next instruction
3822
3823
3824/* ------------------------------ */
3825    .balign 64
3826.L_OP_FLOAT_TO_LONG: /* 0x88 */
3827/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3828@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3829/* File: armv6t2/unopWider.S */
3830    /*
3831     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3832     * that specifies an instruction that performs "result = op r0", where
3833     * "result" is a 64-bit quantity in r0/r1.
3834     *
3835     * For: int-to-long, int-to-double, float-to-long, float-to-double
3836     */
3837    /* unop vA, vB */
3838    mov     r3, rINST, lsr #12          @ r3<- B
3839    ubfx    r9, rINST, #8, #4           @ r9<- A
3840    GET_VREG(r0, r3)                    @ r0<- vB
3841    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3842                               @ optional op; may set condition codes
3843    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3844    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3846    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3847    GOTO_OPCODE(ip)                     @ jump to next instruction
3848    /* 9-10 instructions */
3849
3850
3851
3852/* ------------------------------ */
3853    .balign 64
3854.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3855/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3856/* File: arm-vfp/funopWider.S */
3857    /*
3858     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3859     * "instr" line that specifies an instruction that performs "d0 = op s0".
3860     *
3861     * For: int-to-double, float-to-double
3862     */
3863    /* unop vA, vB */
3864    mov     r3, rINST, lsr #12          @ r3<- B
3865    mov     r9, rINST, lsr #8           @ r9<- A+
3866    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3867    flds    s0, [r3]                    @ s0<- vB
3868    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3869    and     r9, r9, #15                 @ r9<- A
3870    fcvtds  d0, s0                              @ d0<- op
3871    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3872    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3873    fstd    d0, [r9]                    @ vA<- d0
3874    GOTO_OPCODE(ip)                     @ jump to next instruction
3875
3876
3877/* ------------------------------ */
3878    .balign 64
3879.L_OP_DOUBLE_TO_INT: /* 0x8a */
3880/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3881/* File: arm-vfp/funopNarrower.S */
3882    /*
3883     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3884     * "instr" line that specifies an instruction that performs "s0 = op d0".
3885     *
3886     * For: double-to-int, double-to-float
3887     */
3888    /* unop vA, vB */
3889    mov     r3, rINST, lsr #12          @ r3<- B
3890    mov     r9, rINST, lsr #8           @ r9<- A+
3891    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3892    fldd    d0, [r3]                    @ d0<- vB
3893    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3894    and     r9, r9, #15                 @ r9<- A
3895    ftosizd  s0, d0                              @ s0<- op
3896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3897    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3898    fsts    s0, [r9]                    @ vA<- s0
3899    GOTO_OPCODE(ip)                     @ jump to next instruction
3900
3901
3902/* ------------------------------ */
3903    .balign 64
3904.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3905/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3906@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3907/* File: armv6t2/unopWide.S */
3908    /*
3909     * Generic 64-bit unary operation.  Provide an "instr" line that
3910     * specifies an instruction that performs "result = op r0/r1".
3911     * This could be an ARM instruction or a function call.
3912     *
3913     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3914     */
3915    /* unop vA, vB */
3916    mov     r3, rINST, lsr #12          @ r3<- B
3917    ubfx    r9, rINST, #8, #4           @ r9<- A
3918    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3919    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3920    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3921    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3922                               @ optional op; may set condition codes
3923    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3925    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3926    GOTO_OPCODE(ip)                     @ jump to next instruction
3927    /* 10-11 instructions */
3928
3929
3930
3931/* ------------------------------ */
3932    .balign 64
3933.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3934/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3935/* File: arm-vfp/funopNarrower.S */
3936    /*
3937     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3938     * "instr" line that specifies an instruction that performs "s0 = op d0".
3939     *
3940     * For: double-to-int, double-to-float
3941     */
3942    /* unop vA, vB */
3943    mov     r3, rINST, lsr #12          @ r3<- B
3944    mov     r9, rINST, lsr #8           @ r9<- A+
3945    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3946    fldd    d0, [r3]                    @ d0<- vB
3947    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3948    and     r9, r9, #15                 @ r9<- A
3949    fcvtsd  s0, d0                              @ s0<- op
3950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3951    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3952    fsts    s0, [r9]                    @ vA<- s0
3953    GOTO_OPCODE(ip)                     @ jump to next instruction
3954
3955
3956/* ------------------------------ */
3957    .balign 64
3958.L_OP_INT_TO_BYTE: /* 0x8d */
3959/* File: armv6t2/OP_INT_TO_BYTE.S */
3960/* File: armv6t2/unop.S */
3961    /*
3962     * Generic 32-bit unary operation.  Provide an "instr" line that
3963     * specifies an instruction that performs "result = op r0".
3964     * This could be an ARM instruction or a function call.
3965     *
3966     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3967     *      int-to-byte, int-to-char, int-to-short
3968     */
3969    /* unop vA, vB */
3970    mov     r3, rINST, lsr #12          @ r3<- B
3971    ubfx    r9, rINST, #8, #4           @ r9<- A
3972    GET_VREG(r0, r3)                    @ r0<- vB
3973                               @ optional op; may set condition codes
3974    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3975    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3977    SET_VREG(r0, r9)                    @ vAA<- r0
3978    GOTO_OPCODE(ip)                     @ jump to next instruction
3979    /* 8-9 instructions */
3980
3981
3982/* ------------------------------ */
3983    .balign 64
3984.L_OP_INT_TO_CHAR: /* 0x8e */
3985/* File: armv6t2/OP_INT_TO_CHAR.S */
3986/* File: armv6t2/unop.S */
3987    /*
3988     * Generic 32-bit unary operation.  Provide an "instr" line that
3989     * specifies an instruction that performs "result = op r0".
3990     * This could be an ARM instruction or a function call.
3991     *
3992     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3993     *      int-to-byte, int-to-char, int-to-short
3994     */
3995    /* unop vA, vB */
3996    mov     r3, rINST, lsr #12          @ r3<- B
3997    ubfx    r9, rINST, #8, #4           @ r9<- A
3998    GET_VREG(r0, r3)                    @ r0<- vB
3999                               @ optional op; may set condition codes
4000    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4001    uxth    r0, r0                              @ r0<- op, r0-r3 changed
4002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4003    SET_VREG(r0, r9)                    @ vAA<- r0
4004    GOTO_OPCODE(ip)                     @ jump to next instruction
4005    /* 8-9 instructions */
4006
4007
4008/* ------------------------------ */
4009    .balign 64
4010.L_OP_INT_TO_SHORT: /* 0x8f */
4011/* File: armv6t2/OP_INT_TO_SHORT.S */
4012/* File: armv6t2/unop.S */
4013    /*
4014     * Generic 32-bit unary operation.  Provide an "instr" line that
4015     * specifies an instruction that performs "result = op r0".
4016     * This could be an ARM instruction or a function call.
4017     *
4018     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4019     *      int-to-byte, int-to-char, int-to-short
4020     */
4021    /* unop vA, vB */
4022    mov     r3, rINST, lsr #12          @ r3<- B
4023    ubfx    r9, rINST, #8, #4           @ r9<- A
4024    GET_VREG(r0, r3)                    @ r0<- vB
4025                               @ optional op; may set condition codes
4026    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4027    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4028    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4029    SET_VREG(r0, r9)                    @ vAA<- r0
4030    GOTO_OPCODE(ip)                     @ jump to next instruction
4031    /* 8-9 instructions */
4032
4033
4034/* ------------------------------ */
4035    .balign 64
4036.L_OP_ADD_INT: /* 0x90 */
4037/* File: armv5te/OP_ADD_INT.S */
4038/* File: armv5te/binop.S */
4039    /*
4040     * Generic 32-bit binary operation.  Provide an "instr" line that
4041     * specifies an instruction that performs "result = r0 op r1".
4042     * This could be an ARM instruction or a function call.  (If the result
4043     * comes back in a register other than r0, you can override "result".)
4044     *
4045     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4046     * vCC (r1).  Useful for integer division and modulus.  Note that we
4047     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4048     * handles it correctly.
4049     *
4050     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4051     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4052     *      mul-float, div-float, rem-float
4053     */
4054    /* binop vAA, vBB, vCC */
4055    FETCH(r0, 1)                        @ r0<- CCBB
4056    mov     r9, rINST, lsr #8           @ r9<- AA
4057    mov     r3, r0, lsr #8              @ r3<- CC
4058    and     r2, r0, #255                @ r2<- BB
4059    GET_VREG(r1, r3)                    @ r1<- vCC
4060    GET_VREG(r0, r2)                    @ r0<- vBB
4061    .if 0
4062    cmp     r1, #0                      @ is second operand zero?
4063    beq     common_errDivideByZero
4064    .endif
4065
4066    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4067                               @ optional op; may set condition codes
4068    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4070    SET_VREG(r0, r9)               @ vAA<- r0
4071    GOTO_OPCODE(ip)                     @ jump to next instruction
4072    /* 11-14 instructions */
4073
4074
4075/* ------------------------------ */
4076    .balign 64
4077.L_OP_SUB_INT: /* 0x91 */
4078/* File: armv5te/OP_SUB_INT.S */
4079/* File: armv5te/binop.S */
4080    /*
4081     * Generic 32-bit binary operation.  Provide an "instr" line that
4082     * specifies an instruction that performs "result = r0 op r1".
4083     * This could be an ARM instruction or a function call.  (If the result
4084     * comes back in a register other than r0, you can override "result".)
4085     *
4086     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4087     * vCC (r1).  Useful for integer division and modulus.  Note that we
4088     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4089     * handles it correctly.
4090     *
4091     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4092     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4093     *      mul-float, div-float, rem-float
4094     */
4095    /* binop vAA, vBB, vCC */
4096    FETCH(r0, 1)                        @ r0<- CCBB
4097    mov     r9, rINST, lsr #8           @ r9<- AA
4098    mov     r3, r0, lsr #8              @ r3<- CC
4099    and     r2, r0, #255                @ r2<- BB
4100    GET_VREG(r1, r3)                    @ r1<- vCC
4101    GET_VREG(r0, r2)                    @ r0<- vBB
4102    .if 0
4103    cmp     r1, #0                      @ is second operand zero?
4104    beq     common_errDivideByZero
4105    .endif
4106
4107    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4108                               @ optional op; may set condition codes
4109    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4110    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4111    SET_VREG(r0, r9)               @ vAA<- r0
4112    GOTO_OPCODE(ip)                     @ jump to next instruction
4113    /* 11-14 instructions */
4114
4115
4116/* ------------------------------ */
4117    .balign 64
4118.L_OP_MUL_INT: /* 0x92 */
4119/* File: armv5te/OP_MUL_INT.S */
4120/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4121/* File: armv5te/binop.S */
4122    /*
4123     * Generic 32-bit binary operation.  Provide an "instr" line that
4124     * specifies an instruction that performs "result = r0 op r1".
4125     * This could be an ARM instruction or a function call.  (If the result
4126     * comes back in a register other than r0, you can override "result".)
4127     *
4128     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4129     * vCC (r1).  Useful for integer division and modulus.  Note that we
4130     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4131     * handles it correctly.
4132     *
4133     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4134     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4135     *      mul-float, div-float, rem-float
4136     */
4137    /* binop vAA, vBB, vCC */
4138    FETCH(r0, 1)                        @ r0<- CCBB
4139    mov     r9, rINST, lsr #8           @ r9<- AA
4140    mov     r3, r0, lsr #8              @ r3<- CC
4141    and     r2, r0, #255                @ r2<- BB
4142    GET_VREG(r1, r3)                    @ r1<- vCC
4143    GET_VREG(r0, r2)                    @ r0<- vBB
4144    .if 0
4145    cmp     r1, #0                      @ is second operand zero?
4146    beq     common_errDivideByZero
4147    .endif
4148
4149    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4150                               @ optional op; may set condition codes
4151    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4153    SET_VREG(r0, r9)               @ vAA<- r0
4154    GOTO_OPCODE(ip)                     @ jump to next instruction
4155    /* 11-14 instructions */
4156
4157
4158/* ------------------------------ */
4159    .balign 64
4160.L_OP_DIV_INT: /* 0x93 */
4161/* File: armv5te/OP_DIV_INT.S */
4162/* File: armv5te/binop.S */
4163    /*
4164     * Generic 32-bit binary operation.  Provide an "instr" line that
4165     * specifies an instruction that performs "result = r0 op r1".
4166     * This could be an ARM instruction or a function call.  (If the result
4167     * comes back in a register other than r0, you can override "result".)
4168     *
4169     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4170     * vCC (r1).  Useful for integer division and modulus.  Note that we
4171     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4172     * handles it correctly.
4173     *
4174     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4175     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4176     *      mul-float, div-float, rem-float
4177     */
4178    /* binop vAA, vBB, vCC */
4179    FETCH(r0, 1)                        @ r0<- CCBB
4180    mov     r9, rINST, lsr #8           @ r9<- AA
4181    mov     r3, r0, lsr #8              @ r3<- CC
4182    and     r2, r0, #255                @ r2<- BB
4183    GET_VREG(r1, r3)                    @ r1<- vCC
4184    GET_VREG(r0, r2)                    @ r0<- vBB
4185    .if 1
4186    cmp     r1, #0                      @ is second operand zero?
4187    beq     common_errDivideByZero
4188    .endif
4189
4190    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4191                               @ optional op; may set condition codes
4192    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4194    SET_VREG(r0, r9)               @ vAA<- r0
4195    GOTO_OPCODE(ip)                     @ jump to next instruction
4196    /* 11-14 instructions */
4197
4198
4199/* ------------------------------ */
4200    .balign 64
4201.L_OP_REM_INT: /* 0x94 */
4202/* File: armv5te/OP_REM_INT.S */
4203/* idivmod returns quotient in r0 and remainder in r1 */
4204/* File: armv5te/binop.S */
4205    /*
4206     * Generic 32-bit binary operation.  Provide an "instr" line that
4207     * specifies an instruction that performs "result = r0 op r1".
4208     * This could be an ARM instruction or a function call.  (If the result
4209     * comes back in a register other than r0, you can override "result".)
4210     *
4211     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4212     * vCC (r1).  Useful for integer division and modulus.  Note that we
4213     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4214     * handles it correctly.
4215     *
4216     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4217     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4218     *      mul-float, div-float, rem-float
4219     */
4220    /* binop vAA, vBB, vCC */
4221    FETCH(r0, 1)                        @ r0<- CCBB
4222    mov     r9, rINST, lsr #8           @ r9<- AA
4223    mov     r3, r0, lsr #8              @ r3<- CC
4224    and     r2, r0, #255                @ r2<- BB
4225    GET_VREG(r1, r3)                    @ r1<- vCC
4226    GET_VREG(r0, r2)                    @ r0<- vBB
4227    .if 1
4228    cmp     r1, #0                      @ is second operand zero?
4229    beq     common_errDivideByZero
4230    .endif
4231
4232    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4233                               @ optional op; may set condition codes
4234    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4236    SET_VREG(r1, r9)               @ vAA<- r1
4237    GOTO_OPCODE(ip)                     @ jump to next instruction
4238    /* 11-14 instructions */
4239
4240
4241/* ------------------------------ */
4242    .balign 64
4243.L_OP_AND_INT: /* 0x95 */
4244/* File: armv5te/OP_AND_INT.S */
4245/* File: armv5te/binop.S */
4246    /*
4247     * Generic 32-bit binary operation.  Provide an "instr" line that
4248     * specifies an instruction that performs "result = r0 op r1".
4249     * This could be an ARM instruction or a function call.  (If the result
4250     * comes back in a register other than r0, you can override "result".)
4251     *
4252     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4253     * vCC (r1).  Useful for integer division and modulus.  Note that we
4254     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4255     * handles it correctly.
4256     *
4257     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4258     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4259     *      mul-float, div-float, rem-float
4260     */
4261    /* binop vAA, vBB, vCC */
4262    FETCH(r0, 1)                        @ r0<- CCBB
4263    mov     r9, rINST, lsr #8           @ r9<- AA
4264    mov     r3, r0, lsr #8              @ r3<- CC
4265    and     r2, r0, #255                @ r2<- BB
4266    GET_VREG(r1, r3)                    @ r1<- vCC
4267    GET_VREG(r0, r2)                    @ r0<- vBB
4268    .if 0
4269    cmp     r1, #0                      @ is second operand zero?
4270    beq     common_errDivideByZero
4271    .endif
4272
4273    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4274                               @ optional op; may set condition codes
4275    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4276    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4277    SET_VREG(r0, r9)               @ vAA<- r0
4278    GOTO_OPCODE(ip)                     @ jump to next instruction
4279    /* 11-14 instructions */
4280
4281
4282/* ------------------------------ */
4283    .balign 64
4284.L_OP_OR_INT: /* 0x96 */
4285/* File: armv5te/OP_OR_INT.S */
4286/* File: armv5te/binop.S */
4287    /*
4288     * Generic 32-bit binary operation.  Provide an "instr" line that
4289     * specifies an instruction that performs "result = r0 op r1".
4290     * This could be an ARM instruction or a function call.  (If the result
4291     * comes back in a register other than r0, you can override "result".)
4292     *
4293     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4294     * vCC (r1).  Useful for integer division and modulus.  Note that we
4295     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4296     * handles it correctly.
4297     *
4298     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4299     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4300     *      mul-float, div-float, rem-float
4301     */
4302    /* binop vAA, vBB, vCC */
4303    FETCH(r0, 1)                        @ r0<- CCBB
4304    mov     r9, rINST, lsr #8           @ r9<- AA
4305    mov     r3, r0, lsr #8              @ r3<- CC
4306    and     r2, r0, #255                @ r2<- BB
4307    GET_VREG(r1, r3)                    @ r1<- vCC
4308    GET_VREG(r0, r2)                    @ r0<- vBB
4309    .if 0
4310    cmp     r1, #0                      @ is second operand zero?
4311    beq     common_errDivideByZero
4312    .endif
4313
4314    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4315                               @ optional op; may set condition codes
4316    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4317    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4318    SET_VREG(r0, r9)               @ vAA<- r0
4319    GOTO_OPCODE(ip)                     @ jump to next instruction
4320    /* 11-14 instructions */
4321
4322
4323/* ------------------------------ */
4324    .balign 64
4325.L_OP_XOR_INT: /* 0x97 */
4326/* File: armv5te/OP_XOR_INT.S */
4327/* File: armv5te/binop.S */
4328    /*
4329     * Generic 32-bit binary operation.  Provide an "instr" line that
4330     * specifies an instruction that performs "result = r0 op r1".
4331     * This could be an ARM instruction or a function call.  (If the result
4332     * comes back in a register other than r0, you can override "result".)
4333     *
4334     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4335     * vCC (r1).  Useful for integer division and modulus.  Note that we
4336     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4337     * handles it correctly.
4338     *
4339     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4340     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4341     *      mul-float, div-float, rem-float
4342     */
4343    /* binop vAA, vBB, vCC */
4344    FETCH(r0, 1)                        @ r0<- CCBB
4345    mov     r9, rINST, lsr #8           @ r9<- AA
4346    mov     r3, r0, lsr #8              @ r3<- CC
4347    and     r2, r0, #255                @ r2<- BB
4348    GET_VREG(r1, r3)                    @ r1<- vCC
4349    GET_VREG(r0, r2)                    @ r0<- vBB
4350    .if 0
4351    cmp     r1, #0                      @ is second operand zero?
4352    beq     common_errDivideByZero
4353    .endif
4354
4355    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4356                               @ optional op; may set condition codes
4357    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4358    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4359    SET_VREG(r0, r9)               @ vAA<- r0
4360    GOTO_OPCODE(ip)                     @ jump to next instruction
4361    /* 11-14 instructions */
4362
4363
4364/* ------------------------------ */
4365    .balign 64
4366.L_OP_SHL_INT: /* 0x98 */
4367/* File: armv5te/OP_SHL_INT.S */
4368/* File: armv5te/binop.S */
4369    /*
4370     * Generic 32-bit binary operation.  Provide an "instr" line that
4371     * specifies an instruction that performs "result = r0 op r1".
4372     * This could be an ARM instruction or a function call.  (If the result
4373     * comes back in a register other than r0, you can override "result".)
4374     *
4375     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4376     * vCC (r1).  Useful for integer division and modulus.  Note that we
4377     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4378     * handles it correctly.
4379     *
4380     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4381     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4382     *      mul-float, div-float, rem-float
4383     */
4384    /* binop vAA, vBB, vCC */
4385    FETCH(r0, 1)                        @ r0<- CCBB
4386    mov     r9, rINST, lsr #8           @ r9<- AA
4387    mov     r3, r0, lsr #8              @ r3<- CC
4388    and     r2, r0, #255                @ r2<- BB
4389    GET_VREG(r1, r3)                    @ r1<- vCC
4390    GET_VREG(r0, r2)                    @ r0<- vBB
4391    .if 0
4392    cmp     r1, #0                      @ is second operand zero?
4393    beq     common_errDivideByZero
4394    .endif
4395
4396    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4397    and     r1, r1, #31                           @ optional op; may set condition codes
4398    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4399    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4400    SET_VREG(r0, r9)               @ vAA<- r0
4401    GOTO_OPCODE(ip)                     @ jump to next instruction
4402    /* 11-14 instructions */
4403
4404
4405/* ------------------------------ */
4406    .balign 64
4407.L_OP_SHR_INT: /* 0x99 */
4408/* File: armv5te/OP_SHR_INT.S */
4409/* File: armv5te/binop.S */
4410    /*
4411     * Generic 32-bit binary operation.  Provide an "instr" line that
4412     * specifies an instruction that performs "result = r0 op r1".
4413     * This could be an ARM instruction or a function call.  (If the result
4414     * comes back in a register other than r0, you can override "result".)
4415     *
4416     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4417     * vCC (r1).  Useful for integer division and modulus.  Note that we
4418     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4419     * handles it correctly.
4420     *
4421     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4422     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4423     *      mul-float, div-float, rem-float
4424     */
4425    /* binop vAA, vBB, vCC */
4426    FETCH(r0, 1)                        @ r0<- CCBB
4427    mov     r9, rINST, lsr #8           @ r9<- AA
4428    mov     r3, r0, lsr #8              @ r3<- CC
4429    and     r2, r0, #255                @ r2<- BB
4430    GET_VREG(r1, r3)                    @ r1<- vCC
4431    GET_VREG(r0, r2)                    @ r0<- vBB
4432    .if 0
4433    cmp     r1, #0                      @ is second operand zero?
4434    beq     common_errDivideByZero
4435    .endif
4436
4437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4438    and     r1, r1, #31                           @ optional op; may set condition codes
4439    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4441    SET_VREG(r0, r9)               @ vAA<- r0
4442    GOTO_OPCODE(ip)                     @ jump to next instruction
4443    /* 11-14 instructions */
4444
4445
4446/* ------------------------------ */
4447    .balign 64
4448.L_OP_USHR_INT: /* 0x9a */
4449/* File: armv5te/OP_USHR_INT.S */
4450/* File: armv5te/binop.S */
4451    /*
4452     * Generic 32-bit binary operation.  Provide an "instr" line that
4453     * specifies an instruction that performs "result = r0 op r1".
4454     * This could be an ARM instruction or a function call.  (If the result
4455     * comes back in a register other than r0, you can override "result".)
4456     *
4457     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4458     * vCC (r1).  Useful for integer division and modulus.  Note that we
4459     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4460     * handles it correctly.
4461     *
4462     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4463     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4464     *      mul-float, div-float, rem-float
4465     */
4466    /* binop vAA, vBB, vCC */
4467    FETCH(r0, 1)                        @ r0<- CCBB
4468    mov     r9, rINST, lsr #8           @ r9<- AA
4469    mov     r3, r0, lsr #8              @ r3<- CC
4470    and     r2, r0, #255                @ r2<- BB
4471    GET_VREG(r1, r3)                    @ r1<- vCC
4472    GET_VREG(r0, r2)                    @ r0<- vBB
4473    .if 0
4474    cmp     r1, #0                      @ is second operand zero?
4475    beq     common_errDivideByZero
4476    .endif
4477
4478    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4479    and     r1, r1, #31                           @ optional op; may set condition codes
4480    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4482    SET_VREG(r0, r9)               @ vAA<- r0
4483    GOTO_OPCODE(ip)                     @ jump to next instruction
4484    /* 11-14 instructions */
4485
4486
4487/* ------------------------------ */
4488    .balign 64
4489.L_OP_ADD_LONG: /* 0x9b */
4490/* File: armv5te/OP_ADD_LONG.S */
4491/* File: armv5te/binopWide.S */
4492    /*
4493     * Generic 64-bit binary operation.  Provide an "instr" line that
4494     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4495     * This could be an ARM instruction or a function call.  (If the result
4496     * comes back in a register other than r0, you can override "result".)
4497     *
4498     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4499     * vCC (r1).  Useful for integer division and modulus.
4500     *
4501     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4502     *      xor-long, add-double, sub-double, mul-double, div-double,
4503     *      rem-double
4504     *
4505     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4506     */
4507    /* binop vAA, vBB, vCC */
4508    FETCH(r0, 1)                        @ r0<- CCBB
4509    mov     r9, rINST, lsr #8           @ r9<- AA
4510    and     r2, r0, #255                @ r2<- BB
4511    mov     r3, r0, lsr #8              @ r3<- CC
4512    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4513    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4514    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4515    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4516    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4517    .if 0
4518    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4519    beq     common_errDivideByZero
4520    .endif
4521    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4522
4523    adds    r0, r0, r2                           @ optional op; may set condition codes
4524    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4525    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4526    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4527    GOTO_OPCODE(ip)                     @ jump to next instruction
4528    /* 14-17 instructions */
4529
4530
4531/* ------------------------------ */
4532    .balign 64
4533.L_OP_SUB_LONG: /* 0x9c */
4534/* File: armv5te/OP_SUB_LONG.S */
4535/* File: armv5te/binopWide.S */
4536    /*
4537     * Generic 64-bit binary operation.  Provide an "instr" line that
4538     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4539     * This could be an ARM instruction or a function call.  (If the result
4540     * comes back in a register other than r0, you can override "result".)
4541     *
4542     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4543     * vCC (r1).  Useful for integer division and modulus.
4544     *
4545     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4546     *      xor-long, add-double, sub-double, mul-double, div-double,
4547     *      rem-double
4548     *
4549     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4550     */
4551    /* binop vAA, vBB, vCC */
4552    FETCH(r0, 1)                        @ r0<- CCBB
4553    mov     r9, rINST, lsr #8           @ r9<- AA
4554    and     r2, r0, #255                @ r2<- BB
4555    mov     r3, r0, lsr #8              @ r3<- CC
4556    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4557    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4558    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4559    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4560    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4561    .if 0
4562    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4563    beq     common_errDivideByZero
4564    .endif
4565    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4566
4567    subs    r0, r0, r2                           @ optional op; may set condition codes
4568    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4569    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4570    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4571    GOTO_OPCODE(ip)                     @ jump to next instruction
4572    /* 14-17 instructions */
4573
4574
4575/* ------------------------------ */
4576    .balign 64
4577.L_OP_MUL_LONG: /* 0x9d */
4578/* File: armv5te/OP_MUL_LONG.S */
4579    /*
4580     * Signed 64-bit integer multiply.
4581     *
4582     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4583     *        WX
4584     *      x YZ
4585     *  --------
4586     *     ZW ZX
4587     *  YW YX
4588     *
4589     * The low word of the result holds ZX, the high word holds
4590     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4591     * it doesn't fit in the low 64 bits.
4592     *
4593     * Unlike most ARM math operations, multiply instructions have
4594     * restrictions on using the same register more than once (Rd and Rm
4595     * cannot be the same).
4596     */
4597    /* mul-long vAA, vBB, vCC */
4598    FETCH(r0, 1)                        @ r0<- CCBB
4599    and     r2, r0, #255                @ r2<- BB
4600    mov     r3, r0, lsr #8              @ r3<- CC
4601    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4602    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4603    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4604    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4605    mul     ip, r2, r1                  @  ip<- ZxW
4606    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4607    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4608    mov     r0, rINST, lsr #8           @ r0<- AA
4609    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4610    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4611    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4612    b       .LOP_MUL_LONG_finish
4613
4614/* ------------------------------ */
4615    .balign 64
4616.L_OP_DIV_LONG: /* 0x9e */
4617/* File: armv5te/OP_DIV_LONG.S */
4618/* File: armv5te/binopWide.S */
4619    /*
4620     * Generic 64-bit binary operation.  Provide an "instr" line that
4621     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4622     * This could be an ARM instruction or a function call.  (If the result
4623     * comes back in a register other than r0, you can override "result".)
4624     *
4625     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4626     * vCC (r1).  Useful for integer division and modulus.
4627     *
4628     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4629     *      xor-long, add-double, sub-double, mul-double, div-double,
4630     *      rem-double
4631     *
4632     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4633     */
4634    /* binop vAA, vBB, vCC */
4635    FETCH(r0, 1)                        @ r0<- CCBB
4636    mov     r9, rINST, lsr #8           @ r9<- AA
4637    and     r2, r0, #255                @ r2<- BB
4638    mov     r3, r0, lsr #8              @ r3<- CC
4639    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4640    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4641    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4642    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4643    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4644    .if 1
4645    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4646    beq     common_errDivideByZero
4647    .endif
4648    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4649
4650                               @ optional op; may set condition codes
4651    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4652    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4653    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4654    GOTO_OPCODE(ip)                     @ jump to next instruction
4655    /* 14-17 instructions */
4656
4657
4658/* ------------------------------ */
4659    .balign 64
4660.L_OP_REM_LONG: /* 0x9f */
4661/* File: armv5te/OP_REM_LONG.S */
4662/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4663/* File: armv5te/binopWide.S */
4664    /*
4665     * Generic 64-bit binary operation.  Provide an "instr" line that
4666     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4667     * This could be an ARM instruction or a function call.  (If the result
4668     * comes back in a register other than r0, you can override "result".)
4669     *
4670     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4671     * vCC (r1).  Useful for integer division and modulus.
4672     *
4673     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4674     *      xor-long, add-double, sub-double, mul-double, div-double,
4675     *      rem-double
4676     *
4677     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4678     */
4679    /* binop vAA, vBB, vCC */
4680    FETCH(r0, 1)                        @ r0<- CCBB
4681    mov     r9, rINST, lsr #8           @ r9<- AA
4682    and     r2, r0, #255                @ r2<- BB
4683    mov     r3, r0, lsr #8              @ r3<- CC
4684    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4685    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4686    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4687    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4688    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4689    .if 1
4690    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4691    beq     common_errDivideByZero
4692    .endif
4693    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4694
4695                               @ optional op; may set condition codes
4696    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4697    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4698    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4699    GOTO_OPCODE(ip)                     @ jump to next instruction
4700    /* 14-17 instructions */
4701
4702
4703/* ------------------------------ */
4704    .balign 64
4705.L_OP_AND_LONG: /* 0xa0 */
4706/* File: armv5te/OP_AND_LONG.S */
4707/* File: armv5te/binopWide.S */
4708    /*
4709     * Generic 64-bit binary operation.  Provide an "instr" line that
4710     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4711     * This could be an ARM instruction or a function call.  (If the result
4712     * comes back in a register other than r0, you can override "result".)
4713     *
4714     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4715     * vCC (r1).  Useful for integer division and modulus.
4716     *
4717     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4718     *      xor-long, add-double, sub-double, mul-double, div-double,
4719     *      rem-double
4720     *
4721     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4722     */
4723    /* binop vAA, vBB, vCC */
4724    FETCH(r0, 1)                        @ r0<- CCBB
4725    mov     r9, rINST, lsr #8           @ r9<- AA
4726    and     r2, r0, #255                @ r2<- BB
4727    mov     r3, r0, lsr #8              @ r3<- CC
4728    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4729    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4730    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4731    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4732    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4733    .if 0
4734    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4735    beq     common_errDivideByZero
4736    .endif
4737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4738
4739    and     r0, r0, r2                           @ optional op; may set condition codes
4740    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4741    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4742    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4743    GOTO_OPCODE(ip)                     @ jump to next instruction
4744    /* 14-17 instructions */
4745
4746
4747/* ------------------------------ */
4748    .balign 64
4749.L_OP_OR_LONG: /* 0xa1 */
4750/* File: armv5te/OP_OR_LONG.S */
4751/* File: armv5te/binopWide.S */
4752    /*
4753     * Generic 64-bit binary operation.  Provide an "instr" line that
4754     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4755     * This could be an ARM instruction or a function call.  (If the result
4756     * comes back in a register other than r0, you can override "result".)
4757     *
4758     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4759     * vCC (r1).  Useful for integer division and modulus.
4760     *
4761     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4762     *      xor-long, add-double, sub-double, mul-double, div-double,
4763     *      rem-double
4764     *
4765     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4766     */
4767    /* binop vAA, vBB, vCC */
4768    FETCH(r0, 1)                        @ r0<- CCBB
4769    mov     r9, rINST, lsr #8           @ r9<- AA
4770    and     r2, r0, #255                @ r2<- BB
4771    mov     r3, r0, lsr #8              @ r3<- CC
4772    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4773    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4774    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4775    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4776    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4777    .if 0
4778    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4779    beq     common_errDivideByZero
4780    .endif
4781    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4782
4783    orr     r0, r0, r2                           @ optional op; may set condition codes
4784    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4785    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4786    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4787    GOTO_OPCODE(ip)                     @ jump to next instruction
4788    /* 14-17 instructions */
4789
4790
4791/* ------------------------------ */
4792    .balign 64
4793.L_OP_XOR_LONG: /* 0xa2 */
4794/* File: armv5te/OP_XOR_LONG.S */
4795/* File: armv5te/binopWide.S */
4796    /*
4797     * Generic 64-bit binary operation.  Provide an "instr" line that
4798     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4799     * This could be an ARM instruction or a function call.  (If the result
4800     * comes back in a register other than r0, you can override "result".)
4801     *
4802     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4803     * vCC (r1).  Useful for integer division and modulus.
4804     *
4805     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4806     *      xor-long, add-double, sub-double, mul-double, div-double,
4807     *      rem-double
4808     *
4809     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4810     */
4811    /* binop vAA, vBB, vCC */
4812    FETCH(r0, 1)                        @ r0<- CCBB
4813    mov     r9, rINST, lsr #8           @ r9<- AA
4814    and     r2, r0, #255                @ r2<- BB
4815    mov     r3, r0, lsr #8              @ r3<- CC
4816    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4817    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4818    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4819    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4820    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4821    .if 0
4822    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4823    beq     common_errDivideByZero
4824    .endif
4825    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4826
4827    eor     r0, r0, r2                           @ optional op; may set condition codes
4828    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4830    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4831    GOTO_OPCODE(ip)                     @ jump to next instruction
4832    /* 14-17 instructions */
4833
4834
4835/* ------------------------------ */
4836    .balign 64
4837.L_OP_SHL_LONG: /* 0xa3 */
4838/* File: armv5te/OP_SHL_LONG.S */
4839    /*
4840     * Long integer shift.  This is different from the generic 32/64-bit
4841     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4842     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4843     * 6 bits of the shift distance.
4844     */
4845    /* shl-long vAA, vBB, vCC */
4846    FETCH(r0, 1)                        @ r0<- CCBB
4847    mov     r9, rINST, lsr #8           @ r9<- AA
4848    and     r3, r0, #255                @ r3<- BB
4849    mov     r0, r0, lsr #8              @ r0<- CC
4850    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4851    GET_VREG(r2, r0)                    @ r2<- vCC
4852    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4853    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4854    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4855
4856    mov     r1, r1, asl r2              @  r1<- r1 << r2
4857    rsb     r3, r2, #32                 @  r3<- 32 - r2
4858    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4859    subs    ip, r2, #32                 @  ip<- r2 - 32
4860    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4861    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4862    b       .LOP_SHL_LONG_finish
4863
4864/* ------------------------------ */
4865    .balign 64
4866.L_OP_SHR_LONG: /* 0xa4 */
4867/* File: armv5te/OP_SHR_LONG.S */
4868    /*
4869     * Long integer shift.  This is different from the generic 32/64-bit
4870     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4871     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4872     * 6 bits of the shift distance.
4873     */
4874    /* shr-long vAA, vBB, vCC */
4875    FETCH(r0, 1)                        @ r0<- CCBB
4876    mov     r9, rINST, lsr #8           @ r9<- AA
4877    and     r3, r0, #255                @ r3<- BB
4878    mov     r0, r0, lsr #8              @ r0<- CC
4879    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4880    GET_VREG(r2, r0)                    @ r2<- vCC
4881    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4882    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4883    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4884
4885    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4886    rsb     r3, r2, #32                 @  r3<- 32 - r2
4887    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4888    subs    ip, r2, #32                 @  ip<- r2 - 32
4889    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4890    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4891    b       .LOP_SHR_LONG_finish
4892
4893/* ------------------------------ */
4894    .balign 64
4895.L_OP_USHR_LONG: /* 0xa5 */
4896/* File: armv5te/OP_USHR_LONG.S */
4897    /*
4898     * Long integer shift.  This is different from the generic 32/64-bit
4899     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4900     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4901     * 6 bits of the shift distance.
4902     */
4903    /* ushr-long vAA, vBB, vCC */
4904    FETCH(r0, 1)                        @ r0<- CCBB
4905    mov     r9, rINST, lsr #8           @ r9<- AA
4906    and     r3, r0, #255                @ r3<- BB
4907    mov     r0, r0, lsr #8              @ r0<- CC
4908    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4909    GET_VREG(r2, r0)                    @ r2<- vCC
4910    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4911    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4912    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4913
4914    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4915    rsb     r3, r2, #32                 @  r3<- 32 - r2
4916    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4917    subs    ip, r2, #32                 @  ip<- r2 - 32
4918    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4919    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4920    b       .LOP_USHR_LONG_finish
4921
4922/* ------------------------------ */
4923    .balign 64
4924.L_OP_ADD_FLOAT: /* 0xa6 */
4925/* File: arm-vfp/OP_ADD_FLOAT.S */
4926/* File: arm-vfp/fbinop.S */
4927    /*
4928     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4929     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4930     * use the "softfp" ABI, this must be an instruction, not a function call.
4931     *
4932     * For: add-float, sub-float, mul-float, div-float
4933     */
4934    /* floatop vAA, vBB, vCC */
4935    FETCH(r0, 1)                        @ r0<- CCBB
4936    mov     r9, rINST, lsr #8           @ r9<- AA
4937    mov     r3, r0, lsr #8              @ r3<- CC
4938    and     r2, r0, #255                @ r2<- BB
4939    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4940    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4941    flds    s1, [r3]                    @ s1<- vCC
4942    flds    s0, [r2]                    @ s0<- vBB
4943
4944    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4945    fadds   s2, s0, s1                              @ s2<- op
4946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4947    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4948    fsts    s2, [r9]                    @ vAA<- s2
4949    GOTO_OPCODE(ip)                     @ jump to next instruction
4950
4951
4952/* ------------------------------ */
4953    .balign 64
4954.L_OP_SUB_FLOAT: /* 0xa7 */
4955/* File: arm-vfp/OP_SUB_FLOAT.S */
4956/* File: arm-vfp/fbinop.S */
4957    /*
4958     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4959     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4960     * use the "softfp" ABI, this must be an instruction, not a function call.
4961     *
4962     * For: add-float, sub-float, mul-float, div-float
4963     */
4964    /* floatop vAA, vBB, vCC */
4965    FETCH(r0, 1)                        @ r0<- CCBB
4966    mov     r9, rINST, lsr #8           @ r9<- AA
4967    mov     r3, r0, lsr #8              @ r3<- CC
4968    and     r2, r0, #255                @ r2<- BB
4969    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4970    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4971    flds    s1, [r3]                    @ s1<- vCC
4972    flds    s0, [r2]                    @ s0<- vBB
4973
4974    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4975    fsubs   s2, s0, s1                              @ s2<- op
4976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4977    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4978    fsts    s2, [r9]                    @ vAA<- s2
4979    GOTO_OPCODE(ip)                     @ jump to next instruction
4980
4981
4982/* ------------------------------ */
4983    .balign 64
4984.L_OP_MUL_FLOAT: /* 0xa8 */
4985/* File: arm-vfp/OP_MUL_FLOAT.S */
4986/* File: arm-vfp/fbinop.S */
4987    /*
4988     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4989     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4990     * use the "softfp" ABI, this must be an instruction, not a function call.
4991     *
4992     * For: add-float, sub-float, mul-float, div-float
4993     */
4994    /* floatop vAA, vBB, vCC */
4995    FETCH(r0, 1)                        @ r0<- CCBB
4996    mov     r9, rINST, lsr #8           @ r9<- AA
4997    mov     r3, r0, lsr #8              @ r3<- CC
4998    and     r2, r0, #255                @ r2<- BB
4999    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5000    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5001    flds    s1, [r3]                    @ s1<- vCC
5002    flds    s0, [r2]                    @ s0<- vBB
5003
5004    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5005    fmuls   s2, s0, s1                              @ s2<- op
5006    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5007    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5008    fsts    s2, [r9]                    @ vAA<- s2
5009    GOTO_OPCODE(ip)                     @ jump to next instruction
5010
5011
5012/* ------------------------------ */
5013    .balign 64
5014.L_OP_DIV_FLOAT: /* 0xa9 */
5015/* File: arm-vfp/OP_DIV_FLOAT.S */
5016/* File: arm-vfp/fbinop.S */
5017    /*
5018     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5019     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5020     * use the "softfp" ABI, this must be an instruction, not a function call.
5021     *
5022     * For: add-float, sub-float, mul-float, div-float
5023     */
5024    /* floatop vAA, vBB, vCC */
5025    FETCH(r0, 1)                        @ r0<- CCBB
5026    mov     r9, rINST, lsr #8           @ r9<- AA
5027    mov     r3, r0, lsr #8              @ r3<- CC
5028    and     r2, r0, #255                @ r2<- BB
5029    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5030    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5031    flds    s1, [r3]                    @ s1<- vCC
5032    flds    s0, [r2]                    @ s0<- vBB
5033
5034    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5035    fdivs   s2, s0, s1                              @ s2<- op
5036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5037    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5038    fsts    s2, [r9]                    @ vAA<- s2
5039    GOTO_OPCODE(ip)                     @ jump to next instruction
5040
5041
5042/* ------------------------------ */
5043    .balign 64
5044.L_OP_REM_FLOAT: /* 0xaa */
5045/* File: armv5te/OP_REM_FLOAT.S */
5046/* EABI doesn't define a float remainder function, but libm does */
5047/* File: armv5te/binop.S */
5048    /*
5049     * Generic 32-bit binary operation.  Provide an "instr" line that
5050     * specifies an instruction that performs "result = r0 op r1".
5051     * This could be an ARM instruction or a function call.  (If the result
5052     * comes back in a register other than r0, you can override "result".)
5053     *
5054     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5055     * vCC (r1).  Useful for integer division and modulus.  Note that we
5056     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5057     * handles it correctly.
5058     *
5059     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5060     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5061     *      mul-float, div-float, rem-float
5062     */
5063    /* binop vAA, vBB, vCC */
5064    FETCH(r0, 1)                        @ r0<- CCBB
5065    mov     r9, rINST, lsr #8           @ r9<- AA
5066    mov     r3, r0, lsr #8              @ r3<- CC
5067    and     r2, r0, #255                @ r2<- BB
5068    GET_VREG(r1, r3)                    @ r1<- vCC
5069    GET_VREG(r0, r2)                    @ r0<- vBB
5070    .if 0
5071    cmp     r1, #0                      @ is second operand zero?
5072    beq     common_errDivideByZero
5073    .endif
5074
5075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5076                               @ optional op; may set condition codes
5077    bl      fmodf                              @ r0<- op, r0-r3 changed
5078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5079    SET_VREG(r0, r9)               @ vAA<- r0
5080    GOTO_OPCODE(ip)                     @ jump to next instruction
5081    /* 11-14 instructions */
5082
5083
5084/* ------------------------------ */
5085    .balign 64
5086.L_OP_ADD_DOUBLE: /* 0xab */
5087/* File: arm-vfp/OP_ADD_DOUBLE.S */
5088/* File: arm-vfp/fbinopWide.S */
5089    /*
5090     * Generic 64-bit double-precision floating point binary operation.
5091     * Provide an "instr" line that specifies an instruction that performs
5092     * "d2 = d0 op d1".
5093     *
5094     * for: add-double, sub-double, mul-double, div-double
5095     */
5096    /* doubleop vAA, vBB, vCC */
5097    FETCH(r0, 1)                        @ r0<- CCBB
5098    mov     r9, rINST, lsr #8           @ r9<- AA
5099    mov     r3, r0, lsr #8              @ r3<- CC
5100    and     r2, r0, #255                @ r2<- BB
5101    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5102    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5103    fldd    d1, [r3]                    @ d1<- vCC
5104    fldd    d0, [r2]                    @ d0<- vBB
5105
5106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5107    faddd   d2, d0, d1                              @ s2<- op
5108    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5109    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5110    fstd    d2, [r9]                    @ vAA<- d2
5111    GOTO_OPCODE(ip)                     @ jump to next instruction
5112
5113
5114/* ------------------------------ */
5115    .balign 64
5116.L_OP_SUB_DOUBLE: /* 0xac */
5117/* File: arm-vfp/OP_SUB_DOUBLE.S */
5118/* File: arm-vfp/fbinopWide.S */
5119    /*
5120     * Generic 64-bit double-precision floating point binary operation.
5121     * Provide an "instr" line that specifies an instruction that performs
5122     * "d2 = d0 op d1".
5123     *
5124     * for: add-double, sub-double, mul-double, div-double
5125     */
5126    /* doubleop vAA, vBB, vCC */
5127    FETCH(r0, 1)                        @ r0<- CCBB
5128    mov     r9, rINST, lsr #8           @ r9<- AA
5129    mov     r3, r0, lsr #8              @ r3<- CC
5130    and     r2, r0, #255                @ r2<- BB
5131    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5132    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5133    fldd    d1, [r3]                    @ d1<- vCC
5134    fldd    d0, [r2]                    @ d0<- vBB
5135
5136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5137    fsubd   d2, d0, d1                              @ s2<- op
5138    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5139    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5140    fstd    d2, [r9]                    @ vAA<- d2
5141    GOTO_OPCODE(ip)                     @ jump to next instruction
5142
5143
5144/* ------------------------------ */
5145    .balign 64
5146.L_OP_MUL_DOUBLE: /* 0xad */
5147/* File: arm-vfp/OP_MUL_DOUBLE.S */
5148/* File: arm-vfp/fbinopWide.S */
5149    /*
5150     * Generic 64-bit double-precision floating point binary operation.
5151     * Provide an "instr" line that specifies an instruction that performs
5152     * "d2 = d0 op d1".
5153     *
5154     * for: add-double, sub-double, mul-double, div-double
5155     */
5156    /* doubleop vAA, vBB, vCC */
5157    FETCH(r0, 1)                        @ r0<- CCBB
5158    mov     r9, rINST, lsr #8           @ r9<- AA
5159    mov     r3, r0, lsr #8              @ r3<- CC
5160    and     r2, r0, #255                @ r2<- BB
5161    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5162    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5163    fldd    d1, [r3]                    @ d1<- vCC
5164    fldd    d0, [r2]                    @ d0<- vBB
5165
5166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5167    fmuld   d2, d0, d1                              @ s2<- op
5168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5169    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5170    fstd    d2, [r9]                    @ vAA<- d2
5171    GOTO_OPCODE(ip)                     @ jump to next instruction
5172
5173
5174/* ------------------------------ */
5175    .balign 64
5176.L_OP_DIV_DOUBLE: /* 0xae */
5177/* File: arm-vfp/OP_DIV_DOUBLE.S */
5178/* File: arm-vfp/fbinopWide.S */
5179    /*
5180     * Generic 64-bit double-precision floating point binary operation.
5181     * Provide an "instr" line that specifies an instruction that performs
5182     * "d2 = d0 op d1".
5183     *
5184     * for: add-double, sub-double, mul-double, div-double
5185     */
5186    /* doubleop vAA, vBB, vCC */
5187    FETCH(r0, 1)                        @ r0<- CCBB
5188    mov     r9, rINST, lsr #8           @ r9<- AA
5189    mov     r3, r0, lsr #8              @ r3<- CC
5190    and     r2, r0, #255                @ r2<- BB
5191    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5192    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5193    fldd    d1, [r3]                    @ d1<- vCC
5194    fldd    d0, [r2]                    @ d0<- vBB
5195
5196    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5197    fdivd   d2, d0, d1                              @ s2<- op
5198    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5199    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5200    fstd    d2, [r9]                    @ vAA<- d2
5201    GOTO_OPCODE(ip)                     @ jump to next instruction
5202
5203
5204/* ------------------------------ */
5205    .balign 64
5206.L_OP_REM_DOUBLE: /* 0xaf */
5207/* File: armv5te/OP_REM_DOUBLE.S */
5208/* EABI doesn't define a double remainder function, but libm does */
5209/* File: armv5te/binopWide.S */
5210    /*
5211     * Generic 64-bit binary operation.  Provide an "instr" line that
5212     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5213     * This could be an ARM instruction or a function call.  (If the result
5214     * comes back in a register other than r0, you can override "result".)
5215     *
5216     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5217     * vCC (r1).  Useful for integer division and modulus.
5218     *
5219     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5220     *      xor-long, add-double, sub-double, mul-double, div-double,
5221     *      rem-double
5222     *
5223     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5224     */
5225    /* binop vAA, vBB, vCC */
5226    FETCH(r0, 1)                        @ r0<- CCBB
5227    mov     r9, rINST, lsr #8           @ r9<- AA
5228    and     r2, r0, #255                @ r2<- BB
5229    mov     r3, r0, lsr #8              @ r3<- CC
5230    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5231    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5232    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5233    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5234    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5235    .if 0
5236    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5237    beq     common_errDivideByZero
5238    .endif
5239    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5240
5241                               @ optional op; may set condition codes
5242    bl      fmod                              @ result<- op, r0-r3 changed
5243    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5244    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5245    GOTO_OPCODE(ip)                     @ jump to next instruction
5246    /* 14-17 instructions */
5247
5248
5249/* ------------------------------ */
5250    .balign 64
5251.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5252/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5253/* File: armv6t2/binop2addr.S */
5254    /*
5255     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5256     * that specifies an instruction that performs "result = r0 op r1".
5257     * This could be an ARM instruction or a function call.  (If the result
5258     * comes back in a register other than r0, you can override "result".)
5259     *
5260     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5261     * vCC (r1).  Useful for integer division and modulus.
5262     *
5263     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5264     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5265     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5266     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5267     */
5268    /* binop/2addr vA, vB */
5269    mov     r3, rINST, lsr #12          @ r3<- B
5270    ubfx    r9, rINST, #8, #4           @ r9<- A
5271    GET_VREG(r1, r3)                    @ r1<- vB
5272    GET_VREG(r0, r9)                    @ r0<- vA
5273    .if 0
5274    cmp     r1, #0                      @ is second operand zero?
5275    beq     common_errDivideByZero
5276    .endif
5277    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5278
5279                               @ optional op; may set condition codes
5280    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5281    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5282    SET_VREG(r0, r9)               @ vAA<- r0
5283    GOTO_OPCODE(ip)                     @ jump to next instruction
5284    /* 10-13 instructions */
5285
5286
5287/* ------------------------------ */
5288    .balign 64
5289.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5290/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5291/* File: armv6t2/binop2addr.S */
5292    /*
5293     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5294     * that specifies an instruction that performs "result = r0 op r1".
5295     * This could be an ARM instruction or a function call.  (If the result
5296     * comes back in a register other than r0, you can override "result".)
5297     *
5298     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5299     * vCC (r1).  Useful for integer division and modulus.
5300     *
5301     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5302     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5303     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5304     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5305     */
5306    /* binop/2addr vA, vB */
5307    mov     r3, rINST, lsr #12          @ r3<- B
5308    ubfx    r9, rINST, #8, #4           @ r9<- A
5309    GET_VREG(r1, r3)                    @ r1<- vB
5310    GET_VREG(r0, r9)                    @ r0<- vA
5311    .if 0
5312    cmp     r1, #0                      @ is second operand zero?
5313    beq     common_errDivideByZero
5314    .endif
5315    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5316
5317                               @ optional op; may set condition codes
5318    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5319    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5320    SET_VREG(r0, r9)               @ vAA<- r0
5321    GOTO_OPCODE(ip)                     @ jump to next instruction
5322    /* 10-13 instructions */
5323
5324
5325/* ------------------------------ */
5326    .balign 64
5327.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5328/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5329/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5330/* File: armv6t2/binop2addr.S */
5331    /*
5332     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5333     * that specifies an instruction that performs "result = r0 op r1".
5334     * This could be an ARM instruction or a function call.  (If the result
5335     * comes back in a register other than r0, you can override "result".)
5336     *
5337     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5338     * vCC (r1).  Useful for integer division and modulus.
5339     *
5340     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5341     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5342     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5343     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5344     */
5345    /* binop/2addr vA, vB */
5346    mov     r3, rINST, lsr #12          @ r3<- B
5347    ubfx    r9, rINST, #8, #4           @ r9<- A
5348    GET_VREG(r1, r3)                    @ r1<- vB
5349    GET_VREG(r0, r9)                    @ r0<- vA
5350    .if 0
5351    cmp     r1, #0                      @ is second operand zero?
5352    beq     common_errDivideByZero
5353    .endif
5354    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5355
5356                               @ optional op; may set condition codes
5357    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5358    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5359    SET_VREG(r0, r9)               @ vAA<- r0
5360    GOTO_OPCODE(ip)                     @ jump to next instruction
5361    /* 10-13 instructions */
5362
5363
5364/* ------------------------------ */
5365    .balign 64
5366.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5367/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5368/* File: armv6t2/binop2addr.S */
5369    /*
5370     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5371     * that specifies an instruction that performs "result = r0 op r1".
5372     * This could be an ARM instruction or a function call.  (If the result
5373     * comes back in a register other than r0, you can override "result".)
5374     *
5375     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5376     * vCC (r1).  Useful for integer division and modulus.
5377     *
5378     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5379     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5380     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5381     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5382     */
5383    /* binop/2addr vA, vB */
5384    mov     r3, rINST, lsr #12          @ r3<- B
5385    ubfx    r9, rINST, #8, #4           @ r9<- A
5386    GET_VREG(r1, r3)                    @ r1<- vB
5387    GET_VREG(r0, r9)                    @ r0<- vA
5388    .if 1
5389    cmp     r1, #0                      @ is second operand zero?
5390    beq     common_errDivideByZero
5391    .endif
5392    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5393
5394                               @ optional op; may set condition codes
5395    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5397    SET_VREG(r0, r9)               @ vAA<- r0
5398    GOTO_OPCODE(ip)                     @ jump to next instruction
5399    /* 10-13 instructions */
5400
5401
5402/* ------------------------------ */
5403    .balign 64
5404.L_OP_REM_INT_2ADDR: /* 0xb4 */
5405/* File: armv6t2/OP_REM_INT_2ADDR.S */
5406/* idivmod returns quotient in r0 and remainder in r1 */
5407/* File: armv6t2/binop2addr.S */
5408    /*
5409     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5410     * that specifies an instruction that performs "result = r0 op r1".
5411     * This could be an ARM instruction or a function call.  (If the result
5412     * comes back in a register other than r0, you can override "result".)
5413     *
5414     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5415     * vCC (r1).  Useful for integer division and modulus.
5416     *
5417     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5418     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5419     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5420     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5421     */
5422    /* binop/2addr vA, vB */
5423    mov     r3, rINST, lsr #12          @ r3<- B
5424    ubfx    r9, rINST, #8, #4           @ r9<- A
5425    GET_VREG(r1, r3)                    @ r1<- vB
5426    GET_VREG(r0, r9)                    @ r0<- vA
5427    .if 1
5428    cmp     r1, #0                      @ is second operand zero?
5429    beq     common_errDivideByZero
5430    .endif
5431    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5432
5433                               @ optional op; may set condition codes
5434    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5435    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5436    SET_VREG(r1, r9)               @ vAA<- r1
5437    GOTO_OPCODE(ip)                     @ jump to next instruction
5438    /* 10-13 instructions */
5439
5440
5441/* ------------------------------ */
5442    .balign 64
5443.L_OP_AND_INT_2ADDR: /* 0xb5 */
5444/* File: armv6t2/OP_AND_INT_2ADDR.S */
5445/* File: armv6t2/binop2addr.S */
5446    /*
5447     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5448     * that specifies an instruction that performs "result = r0 op r1".
5449     * This could be an ARM instruction or a function call.  (If the result
5450     * comes back in a register other than r0, you can override "result".)
5451     *
5452     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5453     * vCC (r1).  Useful for integer division and modulus.
5454     *
5455     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5456     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5457     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5458     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5459     */
5460    /* binop/2addr vA, vB */
5461    mov     r3, rINST, lsr #12          @ r3<- B
5462    ubfx    r9, rINST, #8, #4           @ r9<- A
5463    GET_VREG(r1, r3)                    @ r1<- vB
5464    GET_VREG(r0, r9)                    @ r0<- vA
5465    .if 0
5466    cmp     r1, #0                      @ is second operand zero?
5467    beq     common_errDivideByZero
5468    .endif
5469    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5470
5471                               @ optional op; may set condition codes
5472    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5473    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5474    SET_VREG(r0, r9)               @ vAA<- r0
5475    GOTO_OPCODE(ip)                     @ jump to next instruction
5476    /* 10-13 instructions */
5477
5478
5479/* ------------------------------ */
5480    .balign 64
5481.L_OP_OR_INT_2ADDR: /* 0xb6 */
5482/* File: armv6t2/OP_OR_INT_2ADDR.S */
5483/* File: armv6t2/binop2addr.S */
5484    /*
5485     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5486     * that specifies an instruction that performs "result = r0 op r1".
5487     * This could be an ARM instruction or a function call.  (If the result
5488     * comes back in a register other than r0, you can override "result".)
5489     *
5490     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5491     * vCC (r1).  Useful for integer division and modulus.
5492     *
5493     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5494     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5495     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5496     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5497     */
5498    /* binop/2addr vA, vB */
5499    mov     r3, rINST, lsr #12          @ r3<- B
5500    ubfx    r9, rINST, #8, #4           @ r9<- A
5501    GET_VREG(r1, r3)                    @ r1<- vB
5502    GET_VREG(r0, r9)                    @ r0<- vA
5503    .if 0
5504    cmp     r1, #0                      @ is second operand zero?
5505    beq     common_errDivideByZero
5506    .endif
5507    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5508
5509                               @ optional op; may set condition codes
5510    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5512    SET_VREG(r0, r9)               @ vAA<- r0
5513    GOTO_OPCODE(ip)                     @ jump to next instruction
5514    /* 10-13 instructions */
5515
5516
5517/* ------------------------------ */
5518    .balign 64
5519.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5520/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5521/* File: armv6t2/binop2addr.S */
5522    /*
5523     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5524     * that specifies an instruction that performs "result = r0 op r1".
5525     * This could be an ARM instruction or a function call.  (If the result
5526     * comes back in a register other than r0, you can override "result".)
5527     *
5528     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5529     * vCC (r1).  Useful for integer division and modulus.
5530     *
5531     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5532     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5533     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5534     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5535     */
5536    /* binop/2addr vA, vB */
5537    mov     r3, rINST, lsr #12          @ r3<- B
5538    ubfx    r9, rINST, #8, #4           @ r9<- A
5539    GET_VREG(r1, r3)                    @ r1<- vB
5540    GET_VREG(r0, r9)                    @ r0<- vA
5541    .if 0
5542    cmp     r1, #0                      @ is second operand zero?
5543    beq     common_errDivideByZero
5544    .endif
5545    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5546
5547                               @ optional op; may set condition codes
5548    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5550    SET_VREG(r0, r9)               @ vAA<- r0
5551    GOTO_OPCODE(ip)                     @ jump to next instruction
5552    /* 10-13 instructions */
5553
5554
5555/* ------------------------------ */
5556    .balign 64
5557.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5558/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5559/* File: armv6t2/binop2addr.S */
5560    /*
5561     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5562     * that specifies an instruction that performs "result = r0 op r1".
5563     * This could be an ARM instruction or a function call.  (If the result
5564     * comes back in a register other than r0, you can override "result".)
5565     *
5566     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5567     * vCC (r1).  Useful for integer division and modulus.
5568     *
5569     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5570     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5571     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5572     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5573     */
5574    /* binop/2addr vA, vB */
5575    mov     r3, rINST, lsr #12          @ r3<- B
5576    ubfx    r9, rINST, #8, #4           @ r9<- A
5577    GET_VREG(r1, r3)                    @ r1<- vB
5578    GET_VREG(r0, r9)                    @ r0<- vA
5579    .if 0
5580    cmp     r1, #0                      @ is second operand zero?
5581    beq     common_errDivideByZero
5582    .endif
5583    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5584
5585    and     r1, r1, #31                           @ optional op; may set condition codes
5586    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5587    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5588    SET_VREG(r0, r9)               @ vAA<- r0
5589    GOTO_OPCODE(ip)                     @ jump to next instruction
5590    /* 10-13 instructions */
5591
5592
5593/* ------------------------------ */
5594    .balign 64
5595.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5596/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5597/* File: armv6t2/binop2addr.S */
5598    /*
5599     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5600     * that specifies an instruction that performs "result = r0 op r1".
5601     * This could be an ARM instruction or a function call.  (If the result
5602     * comes back in a register other than r0, you can override "result".)
5603     *
5604     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5605     * vCC (r1).  Useful for integer division and modulus.
5606     *
5607     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5608     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5609     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5610     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5611     */
5612    /* binop/2addr vA, vB */
5613    mov     r3, rINST, lsr #12          @ r3<- B
5614    ubfx    r9, rINST, #8, #4           @ r9<- A
5615    GET_VREG(r1, r3)                    @ r1<- vB
5616    GET_VREG(r0, r9)                    @ r0<- vA
5617    .if 0
5618    cmp     r1, #0                      @ is second operand zero?
5619    beq     common_errDivideByZero
5620    .endif
5621    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5622
5623    and     r1, r1, #31                           @ optional op; may set condition codes
5624    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5626    SET_VREG(r0, r9)               @ vAA<- r0
5627    GOTO_OPCODE(ip)                     @ jump to next instruction
5628    /* 10-13 instructions */
5629
5630
5631/* ------------------------------ */
5632    .balign 64
5633.L_OP_USHR_INT_2ADDR: /* 0xba */
5634/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5635/* File: armv6t2/binop2addr.S */
5636    /*
5637     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5638     * that specifies an instruction that performs "result = r0 op r1".
5639     * This could be an ARM instruction or a function call.  (If the result
5640     * comes back in a register other than r0, you can override "result".)
5641     *
5642     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5643     * vCC (r1).  Useful for integer division and modulus.
5644     *
5645     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5646     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5647     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5648     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5649     */
5650    /* binop/2addr vA, vB */
5651    mov     r3, rINST, lsr #12          @ r3<- B
5652    ubfx    r9, rINST, #8, #4           @ r9<- A
5653    GET_VREG(r1, r3)                    @ r1<- vB
5654    GET_VREG(r0, r9)                    @ r0<- vA
5655    .if 0
5656    cmp     r1, #0                      @ is second operand zero?
5657    beq     common_errDivideByZero
5658    .endif
5659    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5660
5661    and     r1, r1, #31                           @ optional op; may set condition codes
5662    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5663    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5664    SET_VREG(r0, r9)               @ vAA<- r0
5665    GOTO_OPCODE(ip)                     @ jump to next instruction
5666    /* 10-13 instructions */
5667
5668
5669/* ------------------------------ */
5670    .balign 64
5671.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5672/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5673/* File: armv6t2/binopWide2addr.S */
5674    /*
5675     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5676     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5677     * This could be an ARM instruction or a function call.  (If the result
5678     * comes back in a register other than r0, you can override "result".)
5679     *
5680     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5681     * vCC (r1).  Useful for integer division and modulus.
5682     *
5683     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5684     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5685     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5686     *      rem-double/2addr
5687     */
5688    /* binop/2addr vA, vB */
5689    mov     r1, rINST, lsr #12          @ r1<- B
5690    ubfx    r9, rINST, #8, #4           @ r9<- A
5691    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5692    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5693    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5694    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5695    .if 0
5696    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5697    beq     common_errDivideByZero
5698    .endif
5699    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5700
5701    adds    r0, r0, r2                           @ optional op; may set condition codes
5702    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5703    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5704    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5705    GOTO_OPCODE(ip)                     @ jump to next instruction
5706    /* 12-15 instructions */
5707
5708
5709/* ------------------------------ */
5710    .balign 64
5711.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5712/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5713/* File: armv6t2/binopWide2addr.S */
5714    /*
5715     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5716     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5717     * This could be an ARM instruction or a function call.  (If the result
5718     * comes back in a register other than r0, you can override "result".)
5719     *
5720     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5721     * vCC (r1).  Useful for integer division and modulus.
5722     *
5723     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5724     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5725     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5726     *      rem-double/2addr
5727     */
5728    /* binop/2addr vA, vB */
5729    mov     r1, rINST, lsr #12          @ r1<- B
5730    ubfx    r9, rINST, #8, #4           @ r9<- A
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: armv6t2/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     r1, rINST, lsr #12          @ r1<- B
5763    ubfx    r9, rINST, #8, #4           @ r9<- A
5764    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5765    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5766    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5767    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5768    mul     ip, r2, r1                  @  ip<- ZxW
5769    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5770    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5771    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5772    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5773    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5775    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5776    GOTO_OPCODE(ip)                     @ jump to next instruction
5777
5778/* ------------------------------ */
5779    .balign 64
5780.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5781/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5782/* File: armv6t2/binopWide2addr.S */
5783    /*
5784     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5785     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5786     * This could be an ARM instruction or a function call.  (If the result
5787     * comes back in a register other than r0, you can override "result".)
5788     *
5789     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5790     * vCC (r1).  Useful for integer division and modulus.
5791     *
5792     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5793     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5794     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5795     *      rem-double/2addr
5796     */
5797    /* binop/2addr vA, vB */
5798    mov     r1, rINST, lsr #12          @ r1<- B
5799    ubfx    r9, rINST, #8, #4           @ r9<- A
5800    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5801    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5802    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5803    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5804    .if 1
5805    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5806    beq     common_errDivideByZero
5807    .endif
5808    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5809
5810                               @ optional op; may set condition codes
5811    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5813    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5814    GOTO_OPCODE(ip)                     @ jump to next instruction
5815    /* 12-15 instructions */
5816
5817
5818/* ------------------------------ */
5819    .balign 64
5820.L_OP_REM_LONG_2ADDR: /* 0xbf */
5821/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5822/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5823/* File: armv6t2/binopWide2addr.S */
5824    /*
5825     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5826     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5827     * This could be an ARM instruction or a function call.  (If the result
5828     * comes back in a register other than r0, you can override "result".)
5829     *
5830     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5831     * vCC (r1).  Useful for integer division and modulus.
5832     *
5833     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5834     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5835     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5836     *      rem-double/2addr
5837     */
5838    /* binop/2addr vA, vB */
5839    mov     r1, rINST, lsr #12          @ r1<- B
5840    ubfx    r9, rINST, #8, #4           @ r9<- A
5841    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5842    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5843    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5844    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5845    .if 1
5846    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5847    beq     common_errDivideByZero
5848    .endif
5849    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5850
5851                               @ optional op; may set condition codes
5852    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5853    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5854    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5855    GOTO_OPCODE(ip)                     @ jump to next instruction
5856    /* 12-15 instructions */
5857
5858
5859/* ------------------------------ */
5860    .balign 64
5861.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5862/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5863/* File: armv6t2/binopWide2addr.S */
5864    /*
5865     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5866     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5867     * This could be an ARM instruction or a function call.  (If the result
5868     * comes back in a register other than r0, you can override "result".)
5869     *
5870     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5871     * vCC (r1).  Useful for integer division and modulus.
5872     *
5873     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5874     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5875     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5876     *      rem-double/2addr
5877     */
5878    /* binop/2addr vA, vB */
5879    mov     r1, rINST, lsr #12          @ r1<- B
5880    ubfx    r9, rINST, #8, #4           @ r9<- A
5881    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5882    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5883    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5884    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5885    .if 0
5886    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5887    beq     common_errDivideByZero
5888    .endif
5889    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5890
5891    and     r0, r0, r2                           @ optional op; may set condition codes
5892    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5894    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5895    GOTO_OPCODE(ip)                     @ jump to next instruction
5896    /* 12-15 instructions */
5897
5898
5899/* ------------------------------ */
5900    .balign 64
5901.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5902/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5903/* File: armv6t2/binopWide2addr.S */
5904    /*
5905     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5906     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5907     * This could be an ARM instruction or a function call.  (If the result
5908     * comes back in a register other than r0, you can override "result".)
5909     *
5910     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5911     * vCC (r1).  Useful for integer division and modulus.
5912     *
5913     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5914     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5915     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5916     *      rem-double/2addr
5917     */
5918    /* binop/2addr vA, vB */
5919    mov     r1, rINST, lsr #12          @ r1<- B
5920    ubfx    r9, rINST, #8, #4           @ r9<- A
5921    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5922    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5923    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5924    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5925    .if 0
5926    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5927    beq     common_errDivideByZero
5928    .endif
5929    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5930
5931    orr     r0, r0, r2                           @ optional op; may set condition codes
5932    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5934    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5935    GOTO_OPCODE(ip)                     @ jump to next instruction
5936    /* 12-15 instructions */
5937
5938
5939/* ------------------------------ */
5940    .balign 64
5941.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5942/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5943/* File: armv6t2/binopWide2addr.S */
5944    /*
5945     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5946     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5947     * This could be an ARM instruction or a function call.  (If the result
5948     * comes back in a register other than r0, you can override "result".)
5949     *
5950     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5951     * vCC (r1).  Useful for integer division and modulus.
5952     *
5953     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5954     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5955     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5956     *      rem-double/2addr
5957     */
5958    /* binop/2addr vA, vB */
5959    mov     r1, rINST, lsr #12          @ r1<- B
5960    ubfx    r9, rINST, #8, #4           @ r9<- A
5961    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5962    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5963    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5964    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5965    .if 0
5966    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5967    beq     common_errDivideByZero
5968    .endif
5969    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5970
5971    eor     r0, r0, r2                           @ optional op; may set condition codes
5972    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5973    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5974    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5975    GOTO_OPCODE(ip)                     @ jump to next instruction
5976    /* 12-15 instructions */
5977
5978
5979/* ------------------------------ */
5980    .balign 64
5981.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5982/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
5983    /*
5984     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5985     * 32-bit shift distance.
5986     */
5987    /* shl-long/2addr vA, vB */
5988    mov     r3, rINST, lsr #12          @ r3<- B
5989    ubfx    r9, rINST, #8, #4           @ r9<- A
5990    GET_VREG(r2, r3)                    @ r2<- vB
5991    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5992    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5993    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5994
5995    mov     r1, r1, asl r2              @  r1<- r1 << r2
5996    rsb     r3, r2, #32                 @  r3<- 32 - r2
5997    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5998    subs    ip, r2, #32                 @  ip<- r2 - 32
5999    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6000    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6001    mov     r0, r0, asl r2              @  r0<- r0 << r2
6002    b       .LOP_SHL_LONG_2ADDR_finish
6003
6004/* ------------------------------ */
6005    .balign 64
6006.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6007/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6008    /*
6009     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6010     * 32-bit shift distance.
6011     */
6012    /* shr-long/2addr vA, vB */
6013    mov     r3, rINST, lsr #12          @ r3<- B
6014    ubfx    r9, rINST, #8, #4           @ r9<- A
6015    GET_VREG(r2, r3)                    @ r2<- vB
6016    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6017    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6018    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6019
6020    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6021    rsb     r3, r2, #32                 @  r3<- 32 - r2
6022    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6023    subs    ip, r2, #32                 @  ip<- r2 - 32
6024    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6025    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6026    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6027    b       .LOP_SHR_LONG_2ADDR_finish
6028
6029/* ------------------------------ */
6030    .balign 64
6031.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6032/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6033    /*
6034     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6035     * 32-bit shift distance.
6036     */
6037    /* ushr-long/2addr vA, vB */
6038    mov     r3, rINST, lsr #12          @ r3<- B
6039    ubfx    r9, rINST, #8, #4           @ r9<- A
6040    GET_VREG(r2, r3)                    @ r2<- vB
6041    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6042    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6043    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6044
6045    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6046    rsb     r3, r2, #32                 @  r3<- 32 - r2
6047    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6048    subs    ip, r2, #32                 @  ip<- r2 - 32
6049    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6050    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6051    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6052    b       .LOP_USHR_LONG_2ADDR_finish
6053
6054/* ------------------------------ */
6055    .balign 64
6056.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6057/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6058/* File: arm-vfp/fbinop2addr.S */
6059    /*
6060     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6061     * an "instr" line that specifies an instruction that performs
6062     * "s2 = s0 op s1".
6063     *
6064     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6065     */
6066    /* binop/2addr vA, vB */
6067    mov     r3, rINST, lsr #12          @ r3<- B
6068    mov     r9, rINST, lsr #8           @ r9<- A+
6069    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6070    and     r9, r9, #15                 @ r9<- A
6071    flds    s1, [r3]                    @ s1<- vB
6072    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6073    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6074    flds    s0, [r9]                    @ s0<- vA
6075
6076    fadds   s2, s0, s1                              @ s2<- op
6077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6078    fsts    s2, [r9]                    @ vAA<- s2
6079    GOTO_OPCODE(ip)                     @ jump to next instruction
6080
6081
6082/* ------------------------------ */
6083    .balign 64
6084.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6085/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6086/* File: arm-vfp/fbinop2addr.S */
6087    /*
6088     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6089     * an "instr" line that specifies an instruction that performs
6090     * "s2 = s0 op s1".
6091     *
6092     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6093     */
6094    /* binop/2addr vA, vB */
6095    mov     r3, rINST, lsr #12          @ r3<- B
6096    mov     r9, rINST, lsr #8           @ r9<- A+
6097    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6098    and     r9, r9, #15                 @ r9<- A
6099    flds    s1, [r3]                    @ s1<- vB
6100    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6101    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6102    flds    s0, [r9]                    @ s0<- vA
6103
6104    fsubs   s2, s0, s1                              @ s2<- op
6105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6106    fsts    s2, [r9]                    @ vAA<- s2
6107    GOTO_OPCODE(ip)                     @ jump to next instruction
6108
6109
6110/* ------------------------------ */
6111    .balign 64
6112.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6113/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6114/* File: arm-vfp/fbinop2addr.S */
6115    /*
6116     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6117     * an "instr" line that specifies an instruction that performs
6118     * "s2 = s0 op s1".
6119     *
6120     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6121     */
6122    /* binop/2addr vA, vB */
6123    mov     r3, rINST, lsr #12          @ r3<- B
6124    mov     r9, rINST, lsr #8           @ r9<- A+
6125    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6126    and     r9, r9, #15                 @ r9<- A
6127    flds    s1, [r3]                    @ s1<- vB
6128    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6129    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6130    flds    s0, [r9]                    @ s0<- vA
6131
6132    fmuls   s2, s0, s1                              @ s2<- op
6133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6134    fsts    s2, [r9]                    @ vAA<- s2
6135    GOTO_OPCODE(ip)                     @ jump to next instruction
6136
6137
6138/* ------------------------------ */
6139    .balign 64
6140.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6141/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6142/* File: arm-vfp/fbinop2addr.S */
6143    /*
6144     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6145     * an "instr" line that specifies an instruction that performs
6146     * "s2 = s0 op s1".
6147     *
6148     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6149     */
6150    /* binop/2addr vA, vB */
6151    mov     r3, rINST, lsr #12          @ r3<- B
6152    mov     r9, rINST, lsr #8           @ r9<- A+
6153    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6154    and     r9, r9, #15                 @ r9<- A
6155    flds    s1, [r3]                    @ s1<- vB
6156    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6157    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6158    flds    s0, [r9]                    @ s0<- vA
6159
6160    fdivs   s2, s0, s1                              @ s2<- op
6161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6162    fsts    s2, [r9]                    @ vAA<- s2
6163    GOTO_OPCODE(ip)                     @ jump to next instruction
6164
6165
6166/* ------------------------------ */
6167    .balign 64
6168.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6169/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6170/* EABI doesn't define a float remainder function, but libm does */
6171/* File: armv6t2/binop2addr.S */
6172    /*
6173     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6174     * that specifies an instruction that performs "result = r0 op r1".
6175     * This could be an ARM instruction or a function call.  (If the result
6176     * comes back in a register other than r0, you can override "result".)
6177     *
6178     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6179     * vCC (r1).  Useful for integer division and modulus.
6180     *
6181     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6182     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6183     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6184     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6185     */
6186    /* binop/2addr vA, vB */
6187    mov     r3, rINST, lsr #12          @ r3<- B
6188    ubfx    r9, rINST, #8, #4           @ r9<- A
6189    GET_VREG(r1, r3)                    @ r1<- vB
6190    GET_VREG(r0, r9)                    @ r0<- vA
6191    .if 0
6192    cmp     r1, #0                      @ is second operand zero?
6193    beq     common_errDivideByZero
6194    .endif
6195    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6196
6197                               @ optional op; may set condition codes
6198    bl      fmodf                              @ r0<- op, r0-r3 changed
6199    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6200    SET_VREG(r0, r9)               @ vAA<- r0
6201    GOTO_OPCODE(ip)                     @ jump to next instruction
6202    /* 10-13 instructions */
6203
6204
6205/* ------------------------------ */
6206    .balign 64
6207.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6208/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6209/* File: arm-vfp/fbinopWide2addr.S */
6210    /*
6211     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6212     * an "instr" line that specifies an instruction that performs
6213     * "d2 = d0 op d1".
6214     *
6215     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6216     *      div-double/2addr
6217     */
6218    /* binop/2addr vA, vB */
6219    mov     r3, rINST, lsr #12          @ r3<- B
6220    mov     r9, rINST, lsr #8           @ r9<- A+
6221    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6222    and     r9, r9, #15                 @ r9<- A
6223    fldd    d1, [r3]                    @ d1<- vB
6224    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6225    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6226    fldd    d0, [r9]                    @ d0<- vA
6227
6228    faddd   d2, d0, d1                              @ d2<- op
6229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6230    fstd    d2, [r9]                    @ vAA<- d2
6231    GOTO_OPCODE(ip)                     @ jump to next instruction
6232
6233
6234/* ------------------------------ */
6235    .balign 64
6236.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6237/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6238/* File: arm-vfp/fbinopWide2addr.S */
6239    /*
6240     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6241     * an "instr" line that specifies an instruction that performs
6242     * "d2 = d0 op d1".
6243     *
6244     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6245     *      div-double/2addr
6246     */
6247    /* binop/2addr vA, vB */
6248    mov     r3, rINST, lsr #12          @ r3<- B
6249    mov     r9, rINST, lsr #8           @ r9<- A+
6250    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6251    and     r9, r9, #15                 @ r9<- A
6252    fldd    d1, [r3]                    @ d1<- vB
6253    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6254    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6255    fldd    d0, [r9]                    @ d0<- vA
6256
6257    fsubd   d2, d0, d1                              @ d2<- op
6258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6259    fstd    d2, [r9]                    @ vAA<- d2
6260    GOTO_OPCODE(ip)                     @ jump to next instruction
6261
6262
6263/* ------------------------------ */
6264    .balign 64
6265.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6266/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6267/* File: arm-vfp/fbinopWide2addr.S */
6268    /*
6269     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6270     * an "instr" line that specifies an instruction that performs
6271     * "d2 = d0 op d1".
6272     *
6273     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6274     *      div-double/2addr
6275     */
6276    /* binop/2addr vA, vB */
6277    mov     r3, rINST, lsr #12          @ r3<- B
6278    mov     r9, rINST, lsr #8           @ r9<- A+
6279    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6280    and     r9, r9, #15                 @ r9<- A
6281    fldd    d1, [r3]                    @ d1<- vB
6282    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6283    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6284    fldd    d0, [r9]                    @ d0<- vA
6285
6286    fmuld   d2, d0, d1                              @ d2<- op
6287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6288    fstd    d2, [r9]                    @ vAA<- d2
6289    GOTO_OPCODE(ip)                     @ jump to next instruction
6290
6291
6292/* ------------------------------ */
6293    .balign 64
6294.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6295/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6296/* File: arm-vfp/fbinopWide2addr.S */
6297    /*
6298     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6299     * an "instr" line that specifies an instruction that performs
6300     * "d2 = d0 op d1".
6301     *
6302     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6303     *      div-double/2addr
6304     */
6305    /* binop/2addr vA, vB */
6306    mov     r3, rINST, lsr #12          @ r3<- B
6307    mov     r9, rINST, lsr #8           @ r9<- A+
6308    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6309    and     r9, r9, #15                 @ r9<- A
6310    fldd    d1, [r3]                    @ d1<- vB
6311    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6312    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6313    fldd    d0, [r9]                    @ d0<- vA
6314
6315    fdivd   d2, d0, d1                              @ d2<- op
6316    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6317    fstd    d2, [r9]                    @ vAA<- d2
6318    GOTO_OPCODE(ip)                     @ jump to next instruction
6319
6320
6321/* ------------------------------ */
6322    .balign 64
6323.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6324/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6325/* EABI doesn't define a double remainder function, but libm does */
6326/* File: armv6t2/binopWide2addr.S */
6327    /*
6328     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6329     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6330     * This could be an ARM instruction or a function call.  (If the result
6331     * comes back in a register other than r0, you can override "result".)
6332     *
6333     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6334     * vCC (r1).  Useful for integer division and modulus.
6335     *
6336     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6337     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6338     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6339     *      rem-double/2addr
6340     */
6341    /* binop/2addr vA, vB */
6342    mov     r1, rINST, lsr #12          @ r1<- B
6343    ubfx    r9, rINST, #8, #4           @ r9<- A
6344    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6345    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6346    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6347    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6348    .if 0
6349    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6350    beq     common_errDivideByZero
6351    .endif
6352    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6353
6354                               @ optional op; may set condition codes
6355    bl      fmod                              @ result<- op, r0-r3 changed
6356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6357    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6358    GOTO_OPCODE(ip)                     @ jump to next instruction
6359    /* 12-15 instructions */
6360
6361
6362/* ------------------------------ */
6363    .balign 64
6364.L_OP_ADD_INT_LIT16: /* 0xd0 */
6365/* File: armv6t2/OP_ADD_INT_LIT16.S */
6366/* File: armv6t2/binopLit16.S */
6367    /*
6368     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6369     * that specifies an instruction that performs "result = r0 op r1".
6370     * This could be an ARM instruction or a function call.  (If the result
6371     * comes back in a register other than r0, you can override "result".)
6372     *
6373     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6374     * vCC (r1).  Useful for integer division and modulus.
6375     *
6376     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6377     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6378     */
6379    /* binop/lit16 vA, vB, #+CCCC */
6380    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6381    mov     r2, rINST, lsr #12          @ r2<- B
6382    ubfx    r9, rINST, #8, #4           @ r9<- A
6383    GET_VREG(r0, r2)                    @ r0<- vB
6384    .if 0
6385    cmp     r1, #0                      @ is second operand zero?
6386    beq     common_errDivideByZero
6387    .endif
6388    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6389
6390    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6391    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6392    SET_VREG(r0, r9)               @ vAA<- r0
6393    GOTO_OPCODE(ip)                     @ jump to next instruction
6394    /* 10-13 instructions */
6395
6396
6397/* ------------------------------ */
6398    .balign 64
6399.L_OP_RSUB_INT: /* 0xd1 */
6400/* File: armv6t2/OP_RSUB_INT.S */
6401/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6402/* File: armv6t2/binopLit16.S */
6403    /*
6404     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6405     * that specifies an instruction that performs "result = r0 op r1".
6406     * This could be an ARM instruction or a function call.  (If the result
6407     * comes back in a register other than r0, you can override "result".)
6408     *
6409     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6410     * vCC (r1).  Useful for integer division and modulus.
6411     *
6412     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6413     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6414     */
6415    /* binop/lit16 vA, vB, #+CCCC */
6416    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6417    mov     r2, rINST, lsr #12          @ r2<- B
6418    ubfx    r9, rINST, #8, #4           @ r9<- A
6419    GET_VREG(r0, r2)                    @ r0<- vB
6420    .if 0
6421    cmp     r1, #0                      @ is second operand zero?
6422    beq     common_errDivideByZero
6423    .endif
6424    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6425
6426    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6428    SET_VREG(r0, r9)               @ vAA<- r0
6429    GOTO_OPCODE(ip)                     @ jump to next instruction
6430    /* 10-13 instructions */
6431
6432
6433/* ------------------------------ */
6434    .balign 64
6435.L_OP_MUL_INT_LIT16: /* 0xd2 */
6436/* File: armv6t2/OP_MUL_INT_LIT16.S */
6437/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6438/* File: armv6t2/binopLit16.S */
6439    /*
6440     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6441     * that specifies an instruction that performs "result = r0 op r1".
6442     * This could be an ARM instruction or a function call.  (If the result
6443     * comes back in a register other than r0, you can override "result".)
6444     *
6445     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6446     * vCC (r1).  Useful for integer division and modulus.
6447     *
6448     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6449     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6450     */
6451    /* binop/lit16 vA, vB, #+CCCC */
6452    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6453    mov     r2, rINST, lsr #12          @ r2<- B
6454    ubfx    r9, rINST, #8, #4           @ r9<- A
6455    GET_VREG(r0, r2)                    @ r0<- vB
6456    .if 0
6457    cmp     r1, #0                      @ is second operand zero?
6458    beq     common_errDivideByZero
6459    .endif
6460    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6461
6462    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6463    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6464    SET_VREG(r0, r9)               @ vAA<- r0
6465    GOTO_OPCODE(ip)                     @ jump to next instruction
6466    /* 10-13 instructions */
6467
6468
6469/* ------------------------------ */
6470    .balign 64
6471.L_OP_DIV_INT_LIT16: /* 0xd3 */
6472/* File: armv6t2/OP_DIV_INT_LIT16.S */
6473/* File: armv6t2/binopLit16.S */
6474    /*
6475     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6476     * that specifies an instruction that performs "result = r0 op r1".
6477     * This could be an ARM instruction or a function call.  (If the result
6478     * comes back in a register other than r0, you can override "result".)
6479     *
6480     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6481     * vCC (r1).  Useful for integer division and modulus.
6482     *
6483     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6484     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6485     */
6486    /* binop/lit16 vA, vB, #+CCCC */
6487    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6488    mov     r2, rINST, lsr #12          @ r2<- B
6489    ubfx    r9, rINST, #8, #4           @ r9<- A
6490    GET_VREG(r0, r2)                    @ r0<- vB
6491    .if 1
6492    cmp     r1, #0                      @ is second operand zero?
6493    beq     common_errDivideByZero
6494    .endif
6495    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6496
6497    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6498    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6499    SET_VREG(r0, r9)               @ vAA<- r0
6500    GOTO_OPCODE(ip)                     @ jump to next instruction
6501    /* 10-13 instructions */
6502
6503
6504/* ------------------------------ */
6505    .balign 64
6506.L_OP_REM_INT_LIT16: /* 0xd4 */
6507/* File: armv6t2/OP_REM_INT_LIT16.S */
6508/* idivmod returns quotient in r0 and remainder in r1 */
6509/* File: armv6t2/binopLit16.S */
6510    /*
6511     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6512     * that specifies an instruction that performs "result = r0 op r1".
6513     * This could be an ARM instruction or a function call.  (If the result
6514     * comes back in a register other than r0, you can override "result".)
6515     *
6516     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6517     * vCC (r1).  Useful for integer division and modulus.
6518     *
6519     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6520     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6521     */
6522    /* binop/lit16 vA, vB, #+CCCC */
6523    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6524    mov     r2, rINST, lsr #12          @ r2<- B
6525    ubfx    r9, rINST, #8, #4           @ r9<- A
6526    GET_VREG(r0, r2)                    @ r0<- vB
6527    .if 1
6528    cmp     r1, #0                      @ is second operand zero?
6529    beq     common_errDivideByZero
6530    .endif
6531    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6532
6533    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6534    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6535    SET_VREG(r1, r9)               @ vAA<- r1
6536    GOTO_OPCODE(ip)                     @ jump to next instruction
6537    /* 10-13 instructions */
6538
6539
6540/* ------------------------------ */
6541    .balign 64
6542.L_OP_AND_INT_LIT16: /* 0xd5 */
6543/* File: armv6t2/OP_AND_INT_LIT16.S */
6544/* File: armv6t2/binopLit16.S */
6545    /*
6546     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6547     * that specifies an instruction that performs "result = r0 op r1".
6548     * This could be an ARM instruction or a function call.  (If the result
6549     * comes back in a register other than r0, you can override "result".)
6550     *
6551     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6552     * vCC (r1).  Useful for integer division and modulus.
6553     *
6554     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6555     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6556     */
6557    /* binop/lit16 vA, vB, #+CCCC */
6558    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6559    mov     r2, rINST, lsr #12          @ r2<- B
6560    ubfx    r9, rINST, #8, #4           @ r9<- A
6561    GET_VREG(r0, r2)                    @ r0<- vB
6562    .if 0
6563    cmp     r1, #0                      @ is second operand zero?
6564    beq     common_errDivideByZero
6565    .endif
6566    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6567
6568    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6569    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6570    SET_VREG(r0, r9)               @ vAA<- r0
6571    GOTO_OPCODE(ip)                     @ jump to next instruction
6572    /* 10-13 instructions */
6573
6574
6575/* ------------------------------ */
6576    .balign 64
6577.L_OP_OR_INT_LIT16: /* 0xd6 */
6578/* File: armv6t2/OP_OR_INT_LIT16.S */
6579/* File: armv6t2/binopLit16.S */
6580    /*
6581     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6582     * that specifies an instruction that performs "result = r0 op r1".
6583     * This could be an ARM instruction or a function call.  (If the result
6584     * comes back in a register other than r0, you can override "result".)
6585     *
6586     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6587     * vCC (r1).  Useful for integer division and modulus.
6588     *
6589     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6590     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6591     */
6592    /* binop/lit16 vA, vB, #+CCCC */
6593    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6594    mov     r2, rINST, lsr #12          @ r2<- B
6595    ubfx    r9, rINST, #8, #4           @ r9<- A
6596    GET_VREG(r0, r2)                    @ r0<- vB
6597    .if 0
6598    cmp     r1, #0                      @ is second operand zero?
6599    beq     common_errDivideByZero
6600    .endif
6601    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6602
6603    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6604    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6605    SET_VREG(r0, r9)               @ vAA<- r0
6606    GOTO_OPCODE(ip)                     @ jump to next instruction
6607    /* 10-13 instructions */
6608
6609
6610/* ------------------------------ */
6611    .balign 64
6612.L_OP_XOR_INT_LIT16: /* 0xd7 */
6613/* File: armv6t2/OP_XOR_INT_LIT16.S */
6614/* File: armv6t2/binopLit16.S */
6615    /*
6616     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6617     * that specifies an instruction that performs "result = r0 op r1".
6618     * This could be an ARM instruction or a function call.  (If the result
6619     * comes back in a register other than r0, you can override "result".)
6620     *
6621     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6622     * vCC (r1).  Useful for integer division and modulus.
6623     *
6624     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6625     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6626     */
6627    /* binop/lit16 vA, vB, #+CCCC */
6628    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6629    mov     r2, rINST, lsr #12          @ r2<- B
6630    ubfx    r9, rINST, #8, #4           @ r9<- A
6631    GET_VREG(r0, r2)                    @ r0<- vB
6632    .if 0
6633    cmp     r1, #0                      @ is second operand zero?
6634    beq     common_errDivideByZero
6635    .endif
6636    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6637
6638    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6639    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6640    SET_VREG(r0, r9)               @ vAA<- r0
6641    GOTO_OPCODE(ip)                     @ jump to next instruction
6642    /* 10-13 instructions */
6643
6644
6645/* ------------------------------ */
6646    .balign 64
6647.L_OP_ADD_INT_LIT8: /* 0xd8 */
6648/* File: armv5te/OP_ADD_INT_LIT8.S */
6649/* File: armv5te/binopLit8.S */
6650    /*
6651     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6652     * that specifies an instruction that performs "result = r0 op r1".
6653     * This could be an ARM instruction or a function call.  (If the result
6654     * comes back in a register other than r0, you can override "result".)
6655     *
6656     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6657     * vCC (r1).  Useful for integer division and modulus.
6658     *
6659     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6660     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6661     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6662     */
6663    /* binop/lit8 vAA, vBB, #+CC */
6664    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6665    mov     r9, rINST, lsr #8           @ r9<- AA
6666    and     r2, r3, #255                @ r2<- BB
6667    GET_VREG(r0, r2)                    @ r0<- vBB
6668    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6669    .if 0
6670    @cmp     r1, #0                      @ is second operand zero?
6671    beq     common_errDivideByZero
6672    .endif
6673    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6674
6675                               @ optional op; may set condition codes
6676    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6677    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6678    SET_VREG(r0, r9)               @ vAA<- r0
6679    GOTO_OPCODE(ip)                     @ jump to next instruction
6680    /* 10-12 instructions */
6681
6682
6683/* ------------------------------ */
6684    .balign 64
6685.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6686/* File: armv5te/OP_RSUB_INT_LIT8.S */
6687/* File: armv5te/binopLit8.S */
6688    /*
6689     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6690     * that specifies an instruction that performs "result = r0 op r1".
6691     * This could be an ARM instruction or a function call.  (If the result
6692     * comes back in a register other than r0, you can override "result".)
6693     *
6694     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6695     * vCC (r1).  Useful for integer division and modulus.
6696     *
6697     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6698     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6699     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6700     */
6701    /* binop/lit8 vAA, vBB, #+CC */
6702    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6703    mov     r9, rINST, lsr #8           @ r9<- AA
6704    and     r2, r3, #255                @ r2<- BB
6705    GET_VREG(r0, r2)                    @ r0<- vBB
6706    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6707    .if 0
6708    @cmp     r1, #0                      @ is second operand zero?
6709    beq     common_errDivideByZero
6710    .endif
6711    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6712
6713                               @ optional op; may set condition codes
6714    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6716    SET_VREG(r0, r9)               @ vAA<- r0
6717    GOTO_OPCODE(ip)                     @ jump to next instruction
6718    /* 10-12 instructions */
6719
6720
6721/* ------------------------------ */
6722    .balign 64
6723.L_OP_MUL_INT_LIT8: /* 0xda */
6724/* File: armv5te/OP_MUL_INT_LIT8.S */
6725/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6726/* File: armv5te/binopLit8.S */
6727    /*
6728     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6729     * that specifies an instruction that performs "result = r0 op r1".
6730     * This could be an ARM instruction or a function call.  (If the result
6731     * comes back in a register other than r0, you can override "result".)
6732     *
6733     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6734     * vCC (r1).  Useful for integer division and modulus.
6735     *
6736     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6737     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6738     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6739     */
6740    /* binop/lit8 vAA, vBB, #+CC */
6741    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6742    mov     r9, rINST, lsr #8           @ r9<- AA
6743    and     r2, r3, #255                @ r2<- BB
6744    GET_VREG(r0, r2)                    @ r0<- vBB
6745    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6746    .if 0
6747    @cmp     r1, #0                      @ is second operand zero?
6748    beq     common_errDivideByZero
6749    .endif
6750    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6751
6752                               @ optional op; may set condition codes
6753    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6755    SET_VREG(r0, r9)               @ vAA<- r0
6756    GOTO_OPCODE(ip)                     @ jump to next instruction
6757    /* 10-12 instructions */
6758
6759
6760/* ------------------------------ */
6761    .balign 64
6762.L_OP_DIV_INT_LIT8: /* 0xdb */
6763/* File: armv5te/OP_DIV_INT_LIT8.S */
6764/* File: armv5te/binopLit8.S */
6765    /*
6766     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6767     * that specifies an instruction that performs "result = r0 op r1".
6768     * This could be an ARM instruction or a function call.  (If the result
6769     * comes back in a register other than r0, you can override "result".)
6770     *
6771     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6772     * vCC (r1).  Useful for integer division and modulus.
6773     *
6774     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6775     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6776     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6777     */
6778    /* binop/lit8 vAA, vBB, #+CC */
6779    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6780    mov     r9, rINST, lsr #8           @ r9<- AA
6781    and     r2, r3, #255                @ r2<- BB
6782    GET_VREG(r0, r2)                    @ r0<- vBB
6783    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6784    .if 1
6785    @cmp     r1, #0                      @ is second operand zero?
6786    beq     common_errDivideByZero
6787    .endif
6788    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6789
6790                               @ optional op; may set condition codes
6791    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6793    SET_VREG(r0, r9)               @ vAA<- r0
6794    GOTO_OPCODE(ip)                     @ jump to next instruction
6795    /* 10-12 instructions */
6796
6797
6798/* ------------------------------ */
6799    .balign 64
6800.L_OP_REM_INT_LIT8: /* 0xdc */
6801/* File: armv5te/OP_REM_INT_LIT8.S */
6802/* idivmod returns quotient in r0 and remainder in r1 */
6803/* File: armv5te/binopLit8.S */
6804    /*
6805     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6806     * that specifies an instruction that performs "result = r0 op r1".
6807     * This could be an ARM instruction or a function call.  (If the result
6808     * comes back in a register other than r0, you can override "result".)
6809     *
6810     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6811     * vCC (r1).  Useful for integer division and modulus.
6812     *
6813     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6814     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6815     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6816     */
6817    /* binop/lit8 vAA, vBB, #+CC */
6818    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6819    mov     r9, rINST, lsr #8           @ r9<- AA
6820    and     r2, r3, #255                @ r2<- BB
6821    GET_VREG(r0, r2)                    @ r0<- vBB
6822    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6823    .if 1
6824    @cmp     r1, #0                      @ is second operand zero?
6825    beq     common_errDivideByZero
6826    .endif
6827    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6828
6829                               @ optional op; may set condition codes
6830    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6832    SET_VREG(r1, r9)               @ vAA<- r1
6833    GOTO_OPCODE(ip)                     @ jump to next instruction
6834    /* 10-12 instructions */
6835
6836
6837/* ------------------------------ */
6838    .balign 64
6839.L_OP_AND_INT_LIT8: /* 0xdd */
6840/* File: armv5te/OP_AND_INT_LIT8.S */
6841/* File: armv5te/binopLit8.S */
6842    /*
6843     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6844     * that specifies an instruction that performs "result = r0 op r1".
6845     * This could be an ARM instruction or a function call.  (If the result
6846     * comes back in a register other than r0, you can override "result".)
6847     *
6848     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6849     * vCC (r1).  Useful for integer division and modulus.
6850     *
6851     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6852     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6853     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6854     */
6855    /* binop/lit8 vAA, vBB, #+CC */
6856    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6857    mov     r9, rINST, lsr #8           @ r9<- AA
6858    and     r2, r3, #255                @ r2<- BB
6859    GET_VREG(r0, r2)                    @ r0<- vBB
6860    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6861    .if 0
6862    @cmp     r1, #0                      @ is second operand zero?
6863    beq     common_errDivideByZero
6864    .endif
6865    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6866
6867                               @ optional op; may set condition codes
6868    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6870    SET_VREG(r0, r9)               @ vAA<- r0
6871    GOTO_OPCODE(ip)                     @ jump to next instruction
6872    /* 10-12 instructions */
6873
6874
6875/* ------------------------------ */
6876    .balign 64
6877.L_OP_OR_INT_LIT8: /* 0xde */
6878/* File: armv5te/OP_OR_INT_LIT8.S */
6879/* File: armv5te/binopLit8.S */
6880    /*
6881     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6882     * that specifies an instruction that performs "result = r0 op r1".
6883     * This could be an ARM instruction or a function call.  (If the result
6884     * comes back in a register other than r0, you can override "result".)
6885     *
6886     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6887     * vCC (r1).  Useful for integer division and modulus.
6888     *
6889     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6890     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6891     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6892     */
6893    /* binop/lit8 vAA, vBB, #+CC */
6894    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6895    mov     r9, rINST, lsr #8           @ r9<- AA
6896    and     r2, r3, #255                @ r2<- BB
6897    GET_VREG(r0, r2)                    @ r0<- vBB
6898    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6899    .if 0
6900    @cmp     r1, #0                      @ is second operand zero?
6901    beq     common_errDivideByZero
6902    .endif
6903    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6904
6905                               @ optional op; may set condition codes
6906    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6908    SET_VREG(r0, r9)               @ vAA<- r0
6909    GOTO_OPCODE(ip)                     @ jump to next instruction
6910    /* 10-12 instructions */
6911
6912
6913/* ------------------------------ */
6914    .balign 64
6915.L_OP_XOR_INT_LIT8: /* 0xdf */
6916/* File: armv5te/OP_XOR_INT_LIT8.S */
6917/* File: armv5te/binopLit8.S */
6918    /*
6919     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6920     * that specifies an instruction that performs "result = r0 op r1".
6921     * This could be an ARM instruction or a function call.  (If the result
6922     * comes back in a register other than r0, you can override "result".)
6923     *
6924     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6925     * vCC (r1).  Useful for integer division and modulus.
6926     *
6927     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6928     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6929     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6930     */
6931    /* binop/lit8 vAA, vBB, #+CC */
6932    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6933    mov     r9, rINST, lsr #8           @ r9<- AA
6934    and     r2, r3, #255                @ r2<- BB
6935    GET_VREG(r0, r2)                    @ r0<- vBB
6936    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6937    .if 0
6938    @cmp     r1, #0                      @ is second operand zero?
6939    beq     common_errDivideByZero
6940    .endif
6941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6942
6943                               @ optional op; may set condition codes
6944    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6946    SET_VREG(r0, r9)               @ vAA<- r0
6947    GOTO_OPCODE(ip)                     @ jump to next instruction
6948    /* 10-12 instructions */
6949
6950
6951/* ------------------------------ */
6952    .balign 64
6953.L_OP_SHL_INT_LIT8: /* 0xe0 */
6954/* File: armv5te/OP_SHL_INT_LIT8.S */
6955/* File: armv5te/binopLit8.S */
6956    /*
6957     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6958     * that specifies an instruction that performs "result = r0 op r1".
6959     * This could be an ARM instruction or a function call.  (If the result
6960     * comes back in a register other than r0, you can override "result".)
6961     *
6962     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6963     * vCC (r1).  Useful for integer division and modulus.
6964     *
6965     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6966     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6967     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6968     */
6969    /* binop/lit8 vAA, vBB, #+CC */
6970    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6971    mov     r9, rINST, lsr #8           @ r9<- AA
6972    and     r2, r3, #255                @ r2<- BB
6973    GET_VREG(r0, r2)                    @ r0<- vBB
6974    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6975    .if 0
6976    @cmp     r1, #0                      @ is second operand zero?
6977    beq     common_errDivideByZero
6978    .endif
6979    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6980
6981    and     r1, r1, #31                           @ optional op; may set condition codes
6982    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
6983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6984    SET_VREG(r0, r9)               @ vAA<- r0
6985    GOTO_OPCODE(ip)                     @ jump to next instruction
6986    /* 10-12 instructions */
6987
6988
6989/* ------------------------------ */
6990    .balign 64
6991.L_OP_SHR_INT_LIT8: /* 0xe1 */
6992/* File: armv5te/OP_SHR_INT_LIT8.S */
6993/* File: armv5te/binopLit8.S */
6994    /*
6995     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6996     * that specifies an instruction that performs "result = r0 op r1".
6997     * This could be an ARM instruction or a function call.  (If the result
6998     * comes back in a register other than r0, you can override "result".)
6999     *
7000     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7001     * vCC (r1).  Useful for integer division and modulus.
7002     *
7003     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7004     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7005     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7006     */
7007    /* binop/lit8 vAA, vBB, #+CC */
7008    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7009    mov     r9, rINST, lsr #8           @ r9<- AA
7010    and     r2, r3, #255                @ r2<- BB
7011    GET_VREG(r0, r2)                    @ r0<- vBB
7012    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7013    .if 0
7014    @cmp     r1, #0                      @ is second operand zero?
7015    beq     common_errDivideByZero
7016    .endif
7017    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7018
7019    and     r1, r1, #31                           @ optional op; may set condition codes
7020    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7021    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7022    SET_VREG(r0, r9)               @ vAA<- r0
7023    GOTO_OPCODE(ip)                     @ jump to next instruction
7024    /* 10-12 instructions */
7025
7026
7027/* ------------------------------ */
7028    .balign 64
7029.L_OP_USHR_INT_LIT8: /* 0xe2 */
7030/* File: armv5te/OP_USHR_INT_LIT8.S */
7031/* File: armv5te/binopLit8.S */
7032    /*
7033     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7034     * that specifies an instruction that performs "result = r0 op r1".
7035     * This could be an ARM instruction or a function call.  (If the result
7036     * comes back in a register other than r0, you can override "result".)
7037     *
7038     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7039     * vCC (r1).  Useful for integer division and modulus.
7040     *
7041     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7042     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7043     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7044     */
7045    /* binop/lit8 vAA, vBB, #+CC */
7046    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7047    mov     r9, rINST, lsr #8           @ r9<- AA
7048    and     r2, r3, #255                @ r2<- BB
7049    GET_VREG(r0, r2)                    @ r0<- vBB
7050    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7051    .if 0
7052    @cmp     r1, #0                      @ is second operand zero?
7053    beq     common_errDivideByZero
7054    .endif
7055    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7056
7057    and     r1, r1, #31                           @ optional op; may set condition codes
7058    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7059    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7060    SET_VREG(r0, r9)               @ vAA<- r0
7061    GOTO_OPCODE(ip)                     @ jump to next instruction
7062    /* 10-12 instructions */
7063
7064
7065/* ------------------------------ */
7066    .balign 64
7067.L_OP_IGET_VOLATILE: /* 0xe3 */
7068/* File: armv5te/OP_IGET_VOLATILE.S */
7069/* File: armv5te/OP_IGET.S */
7070    /*
7071     * General 32-bit instance field get.
7072     *
7073     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7074     */
7075    /* op vA, vB, field@CCCC */
7076    mov     r0, rINST, lsr #12          @ r0<- B
7077    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7078    FETCH(r1, 1)                        @ r1<- field ref CCCC
7079    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7080    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7081    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7082    cmp     r0, #0                      @ is resolved entry null?
7083    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
70848:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7085    EXPORT_PC()                         @ resolve() could throw
7086    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7087    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7088    cmp     r0, #0
7089    bne     .LOP_IGET_VOLATILE_finish
7090    b       common_exceptionThrown
7091
7092
7093/* ------------------------------ */
7094    .balign 64
7095.L_OP_IPUT_VOLATILE: /* 0xe4 */
7096/* File: armv5te/OP_IPUT_VOLATILE.S */
7097/* File: armv5te/OP_IPUT.S */
7098    /*
7099     * General 32-bit instance field put.
7100     *
7101     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7102     */
7103    /* op vA, vB, field@CCCC */
7104    mov     r0, rINST, lsr #12          @ r0<- B
7105    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7106    FETCH(r1, 1)                        @ r1<- field ref CCCC
7107    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7108    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7109    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7110    cmp     r0, #0                      @ is resolved entry null?
7111    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71128:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7113    EXPORT_PC()                         @ resolve() could throw
7114    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7115    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7116    cmp     r0, #0                      @ success?
7117    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7118    b       common_exceptionThrown
7119
7120
7121/* ------------------------------ */
7122    .balign 64
7123.L_OP_SGET_VOLATILE: /* 0xe5 */
7124/* File: armv5te/OP_SGET_VOLATILE.S */
7125/* File: armv5te/OP_SGET.S */
7126    /*
7127     * General 32-bit SGET handler.
7128     *
7129     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7130     */
7131    /* op vAA, field@BBBB */
7132    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7133    FETCH(r1, 1)                        @ r1<- field ref BBBB
7134    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7135    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7136    cmp     r0, #0                      @ is resolved entry null?
7137    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7138.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7139    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7140    SMP_DMB                            @ acquiring load
7141    mov     r2, rINST, lsr #8           @ r2<- AA
7142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7143    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7145    GOTO_OPCODE(ip)                     @ jump to next instruction
7146
7147
7148/* ------------------------------ */
7149    .balign 64
7150.L_OP_SPUT_VOLATILE: /* 0xe6 */
7151/* File: armv5te/OP_SPUT_VOLATILE.S */
7152/* File: armv5te/OP_SPUT.S */
7153    /*
7154     * General 32-bit SPUT handler.
7155     *
7156     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7157     */
7158    /* op vAA, field@BBBB */
7159    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7160    FETCH(r1, 1)                        @ r1<- field ref BBBB
7161    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7162    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7163    cmp     r0, #0                      @ is resolved entry null?
7164    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7165.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7166    mov     r2, rINST, lsr #8           @ r2<- AA
7167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7168    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7170    SMP_DMB                            @ releasing store
7171    str     r1, [r0, #offStaticField_value] @ field<- vAA
7172    GOTO_OPCODE(ip)                     @ jump to next instruction
7173
7174
7175/* ------------------------------ */
7176    .balign 64
7177.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7178/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7179/* File: armv5te/OP_IGET.S */
7180    /*
7181     * General 32-bit instance field get.
7182     *
7183     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7184     */
7185    /* op vA, vB, field@CCCC */
7186    mov     r0, rINST, lsr #12          @ r0<- B
7187    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7188    FETCH(r1, 1)                        @ r1<- field ref CCCC
7189    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7190    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7191    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7192    cmp     r0, #0                      @ is resolved entry null?
7193    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
71948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7195    EXPORT_PC()                         @ resolve() could throw
7196    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7197    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7198    cmp     r0, #0
7199    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7200    b       common_exceptionThrown
7201
7202
7203/* ------------------------------ */
7204    .balign 64
7205.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7206/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7207/* File: armv5te/OP_IGET_WIDE.S */
7208    /*
7209     * Wide 32-bit instance field get.
7210     */
7211    /* iget-wide vA, vB, field@CCCC */
7212    mov     r0, rINST, lsr #12          @ r0<- B
7213    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7214    FETCH(r1, 1)                        @ r1<- field ref CCCC
7215    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7216    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7217    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7218    cmp     r0, #0                      @ is resolved entry null?
7219    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72208:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7221    EXPORT_PC()                         @ resolve() could throw
7222    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7223    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7224    cmp     r0, #0
7225    bne     .LOP_IGET_WIDE_VOLATILE_finish
7226    b       common_exceptionThrown
7227
7228
7229/* ------------------------------ */
7230    .balign 64
7231.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7232/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7233/* File: armv5te/OP_IPUT_WIDE.S */
7234    /* iput-wide vA, vB, field@CCCC */
7235    mov     r0, rINST, lsr #12          @ r0<- B
7236    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7237    FETCH(r1, 1)                        @ r1<- field ref CCCC
7238    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7239    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7240    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7241    cmp     r0, #0                      @ is resolved entry null?
7242    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72438:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7244    EXPORT_PC()                         @ resolve() could throw
7245    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7246    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7247    cmp     r0, #0                      @ success?
7248    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7249    b       common_exceptionThrown
7250
7251
7252/* ------------------------------ */
7253    .balign 64
7254.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7255/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7256/* File: armv5te/OP_SGET_WIDE.S */
7257    /*
7258     * 64-bit SGET handler.
7259     */
7260    /* sget-wide vAA, field@BBBB */
7261    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7262    FETCH(r1, 1)                        @ r1<- field ref BBBB
7263    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7264    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7265    cmp     r0, #0                      @ is resolved entry null?
7266    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7267.LOP_SGET_WIDE_VOLATILE_finish:
7268    mov     r9, rINST, lsr #8           @ r9<- AA
7269    .if 1
7270    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7271    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7272    .else
7273    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7274    .endif
7275    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7276    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7277    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7278    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7279    GOTO_OPCODE(ip)                     @ jump to next instruction
7280
7281
7282/* ------------------------------ */
7283    .balign 64
7284.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7285/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7286/* File: armv5te/OP_SPUT_WIDE.S */
7287    /*
7288     * 64-bit SPUT handler.
7289     */
7290    /* sput-wide vAA, field@BBBB */
7291    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7292    FETCH(r1, 1)                        @ r1<- field ref BBBB
7293    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7294    mov     r9, rINST, lsr #8           @ r9<- AA
7295    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7296    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7297    cmp     r2, #0                      @ is resolved entry null?
7298    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7299.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7300    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7301    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7302    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7303    .if 1
7304    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7305    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7306    .else
7307    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7308    .endif
7309    GOTO_OPCODE(r10)                    @ jump to next instruction
7310
7311
7312/* ------------------------------ */
7313    .balign 64
7314.L_OP_BREAKPOINT: /* 0xec */
7315/* File: armv5te/OP_BREAKPOINT.S */
7316/* File: armv5te/unused.S */
7317    bl      common_abort
7318
7319
7320/* ------------------------------ */
7321    .balign 64
7322.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7323/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7324    /*
7325     * Handle a throw-verification-error instruction.  This throws an
7326     * exception for an error discovered during verification.  The
7327     * exception is indicated by AA, with some detail provided by BBBB.
7328     */
7329    /* op AA, ref@BBBB */
7330    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7331    FETCH(r2, 1)                        @ r2<- BBBB
7332    EXPORT_PC()                         @ export the PC
7333    mov     r1, rINST, lsr #8           @ r1<- AA
7334    bl      dvmThrowVerificationError   @ always throws
7335    b       common_exceptionThrown      @ handle exception
7336
7337/* ------------------------------ */
7338    .balign 64
7339.L_OP_EXECUTE_INLINE: /* 0xee */
7340/* File: armv5te/OP_EXECUTE_INLINE.S */
7341    /*
7342     * Execute a "native inline" instruction.
7343     *
7344     * We need to call an InlineOp4Func:
7345     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7346     *
7347     * The first four args are in r0-r3, pointer to return value storage
7348     * is on the stack.  The function's return value is a flag that tells
7349     * us if an exception was thrown.
7350     */
7351    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7352    FETCH(r10, 1)                       @ r10<- BBBB
7353    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7354    EXPORT_PC()                         @ can throw
7355    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7356    mov     r0, rINST, lsr #12          @ r0<- B
7357    str     r1, [sp]                    @ push &glue->retval
7358    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7359    add     sp, sp, #8                  @ pop stack
7360    cmp     r0, #0                      @ test boolean result of inline
7361    beq     common_exceptionThrown      @ returned false, handle exception
7362    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7363    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7364    GOTO_OPCODE(ip)                     @ jump to next instruction
7365
7366/* ------------------------------ */
7367    .balign 64
7368.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7369/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7370    /*
7371     * Execute a "native inline" instruction, using "/range" semantics.
7372     * Same idea as execute-inline, but we get the args differently.
7373     *
7374     * We need to call an InlineOp4Func:
7375     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7376     *
7377     * The first four args are in r0-r3, pointer to return value storage
7378     * is on the stack.  The function's return value is a flag that tells
7379     * us if an exception was thrown.
7380     */
7381    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7382    FETCH(r10, 1)                       @ r10<- BBBB
7383    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7384    EXPORT_PC()                         @ can throw
7385    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7386    mov     r0, rINST, lsr #8           @ r0<- AA
7387    str     r1, [sp]                    @ push &glue->retval
7388    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7389    add     sp, sp, #8                  @ pop stack
7390    cmp     r0, #0                      @ test boolean result of inline
7391    beq     common_exceptionThrown      @ returned false, handle exception
7392    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7393    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7394    GOTO_OPCODE(ip)                     @ jump to next instruction
7395
7396/* ------------------------------ */
7397    .balign 64
7398.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7399/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7400    /*
7401     * invoke-direct-empty is a no-op in a "standard" interpreter.
7402     */
7403    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7404    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7405    GOTO_OPCODE(ip)                     @ execute it
7406
7407/* ------------------------------ */
7408    .balign 64
7409.L_OP_UNUSED_F1: /* 0xf1 */
7410/* File: armv5te/OP_UNUSED_F1.S */
7411/* File: armv5te/unused.S */
7412    bl      common_abort
7413
7414
7415/* ------------------------------ */
7416    .balign 64
7417.L_OP_IGET_QUICK: /* 0xf2 */
7418/* File: armv6t2/OP_IGET_QUICK.S */
7419    /* For: iget-quick, iget-object-quick */
7420    /* op vA, vB, offset@CCCC */
7421    mov     r2, rINST, lsr #12          @ r2<- B
7422    FETCH(r1, 1)                        @ r1<- field byte offset
7423    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7424    ubfx    r2, rINST, #8, #4           @ r2<- A
7425    cmp     r3, #0                      @ check object for null
7426    beq     common_errNullObject        @ object was null
7427    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7428    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7429    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7430    SET_VREG(r0, r2)                    @ fp[A]<- r0
7431    GOTO_OPCODE(ip)                     @ jump to next instruction
7432
7433/* ------------------------------ */
7434    .balign 64
7435.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7436/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7437    /* iget-wide-quick vA, vB, offset@CCCC */
7438    mov     r2, rINST, lsr #12          @ r2<- B
7439    FETCH(ip, 1)                        @ ip<- field byte offset
7440    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7441    ubfx    r2, rINST, #8, #4           @ r2<- A
7442    cmp     r3, #0                      @ check object for null
7443    beq     common_errNullObject        @ object was null
7444    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7445    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7446    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7448    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7449    GOTO_OPCODE(ip)                     @ jump to next instruction
7450
7451/* ------------------------------ */
7452    .balign 64
7453.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7454/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7455/* File: armv5te/OP_IGET_QUICK.S */
7456    /* For: iget-quick, iget-object-quick */
7457    /* op vA, vB, offset@CCCC */
7458    mov     r2, rINST, lsr #12          @ r2<- B
7459    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7460    FETCH(r1, 1)                        @ r1<- field byte offset
7461    cmp     r3, #0                      @ check object for null
7462    mov     r2, rINST, lsr #8           @ r2<- A(+)
7463    beq     common_errNullObject        @ object was null
7464    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7465    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7466    and     r2, r2, #15
7467    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7468    SET_VREG(r0, r2)                    @ fp[A]<- r0
7469    GOTO_OPCODE(ip)                     @ jump to next instruction
7470
7471
7472/* ------------------------------ */
7473    .balign 64
7474.L_OP_IPUT_QUICK: /* 0xf5 */
7475/* File: armv6t2/OP_IPUT_QUICK.S */
7476    /* For: iput-quick, iput-object-quick */
7477    /* op vA, vB, offset@CCCC */
7478    mov     r2, rINST, lsr #12          @ r2<- B
7479    FETCH(r1, 1)                        @ r1<- field byte offset
7480    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7481    ubfx    r2, rINST, #8, #4           @ r2<- A
7482    cmp     r3, #0                      @ check object for null
7483    beq     common_errNullObject        @ object was null
7484    GET_VREG(r0, r2)                    @ r0<- fp[A]
7485    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7486    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7488    GOTO_OPCODE(ip)                     @ jump to next instruction
7489
7490/* ------------------------------ */
7491    .balign 64
7492.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7493/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7494    /* iput-wide-quick vA, vB, offset@CCCC */
7495    mov     r1, rINST, lsr #12          @ r1<- B
7496    ubfx    r0, rINST, #8, #4           @ r0<- A
7497    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7498    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7499    cmp     r2, #0                      @ check object for null
7500    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7501    beq     common_errNullObject        @ object was null
7502    FETCH(r3, 1)                        @ r3<- field byte offset
7503    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7504    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7506    GOTO_OPCODE(ip)                     @ jump to next instruction
7507
7508/* ------------------------------ */
7509    .balign 64
7510.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7511/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7512    /* For: iput-object-quick */
7513    /* op vA, vB, offset@CCCC */
7514    mov     r2, rINST, lsr #12          @ r2<- B
7515    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7516    FETCH(r1, 1)                        @ r1<- field byte offset
7517    cmp     r3, #0                      @ check object for null
7518    mov     r2, rINST, lsr #8           @ r2<- A(+)
7519    beq     common_errNullObject        @ object was null
7520    and     r2, r2, #15
7521    GET_VREG(r0, r2)                    @ r0<- fp[A]
7522    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7523    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7524    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7525    cmp     r0, #0
7526    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
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_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7533/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7534    /*
7535     * Handle an optimized virtual method call.
7536     *
7537     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7538     */
7539    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7540    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7541    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7542    FETCH(r1, 1)                        @ r1<- BBBB
7543    .if     (!0)
7544    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7545    .endif
7546    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7547    cmp     r2, #0                      @ is "this" null?
7548    beq     common_errNullObject        @ null "this", throw exception
7549    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7550    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7551    EXPORT_PC()                         @ invoke must export
7552    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7553    bl      common_invokeMethodNoRange @ continue on
7554
7555/* ------------------------------ */
7556    .balign 64
7557.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7558/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7559/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7560    /*
7561     * Handle an optimized virtual method call.
7562     *
7563     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7564     */
7565    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7566    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7567    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7568    FETCH(r1, 1)                        @ r1<- BBBB
7569    .if     (!1)
7570    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7571    .endif
7572    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7573    cmp     r2, #0                      @ is "this" null?
7574    beq     common_errNullObject        @ null "this", throw exception
7575    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7576    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7577    EXPORT_PC()                         @ invoke must export
7578    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7579    bl      common_invokeMethodRange @ continue on
7580
7581
7582/* ------------------------------ */
7583    .balign 64
7584.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7585/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7586    /*
7587     * Handle an optimized "super" method call.
7588     *
7589     * for: [opt] invoke-super-quick, invoke-super-quick/range
7590     */
7591    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7592    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7593    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7594    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7595    .if     (!0)
7596    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7597    .endif
7598    FETCH(r1, 1)                        @ r1<- BBBB
7599    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7600    EXPORT_PC()                         @ must export for invoke
7601    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7602    GET_VREG(r3, r10)                   @ r3<- "this"
7603    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7604    cmp     r3, #0                      @ null "this" ref?
7605    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7606    beq     common_errNullObject        @ "this" is null, throw exception
7607    bl      common_invokeMethodNoRange @ continue on
7608
7609/* ------------------------------ */
7610    .balign 64
7611.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7612/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7613/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7614    /*
7615     * Handle an optimized "super" method call.
7616     *
7617     * for: [opt] invoke-super-quick, invoke-super-quick/range
7618     */
7619    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7620    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7621    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7622    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7623    .if     (!1)
7624    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7625    .endif
7626    FETCH(r1, 1)                        @ r1<- BBBB
7627    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7628    EXPORT_PC()                         @ must export for invoke
7629    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7630    GET_VREG(r3, r10)                   @ r3<- "this"
7631    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7632    cmp     r3, #0                      @ null "this" ref?
7633    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7634    beq     common_errNullObject        @ "this" is null, throw exception
7635    bl      common_invokeMethodRange @ continue on
7636
7637
7638/* ------------------------------ */
7639    .balign 64
7640.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7641/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7642/* File: armv5te/OP_IPUT_OBJECT.S */
7643    /*
7644     * 32-bit instance field put.
7645     *
7646     * for: iput-object, iput-object-volatile
7647     */
7648    /* op vA, vB, field@CCCC */
7649    mov     r0, rINST, lsr #12          @ r0<- B
7650    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7651    FETCH(r1, 1)                        @ r1<- field ref CCCC
7652    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7653    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7654    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7655    cmp     r0, #0                      @ is resolved entry null?
7656    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76578:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7658    EXPORT_PC()                         @ resolve() could throw
7659    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7660    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7661    cmp     r0, #0                      @ success?
7662    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7663    b       common_exceptionThrown
7664
7665
7666/* ------------------------------ */
7667    .balign 64
7668.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7669/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7670/* File: armv5te/OP_SGET.S */
7671    /*
7672     * General 32-bit SGET handler.
7673     *
7674     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7675     */
7676    /* op vAA, field@BBBB */
7677    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7678    FETCH(r1, 1)                        @ r1<- field ref BBBB
7679    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7680    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7681    cmp     r0, #0                      @ is resolved entry null?
7682    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7683.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7684    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7685    SMP_DMB                            @ acquiring load
7686    mov     r2, rINST, lsr #8           @ r2<- AA
7687    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7688    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7689    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7690    GOTO_OPCODE(ip)                     @ jump to next instruction
7691
7692
7693/* ------------------------------ */
7694    .balign 64
7695.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7696/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7697/* File: armv5te/OP_SPUT_OBJECT.S */
7698    /*
7699     * 32-bit SPUT handler for objects
7700     *
7701     * for: sput-object, sput-object-volatile
7702     */
7703    /* op vAA, field@BBBB */
7704    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7705    FETCH(r1, 1)                        @ r1<- field ref BBBB
7706    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7707    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7708    cmp     r0, #0                      @ is resolved entry null?
7709    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7710    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7711    EXPORT_PC()                         @ resolve() could throw, so export now
7712    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7713    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7714    cmp     r0, #0                      @ success?
7715    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7716    b       common_exceptionThrown      @ no, handle exception
7717
7718
7719
7720/* ------------------------------ */
7721    .balign 64
7722.L_OP_UNUSED_FF: /* 0xff */
7723/* File: armv5te/OP_UNUSED_FF.S */
7724/* File: armv5te/unused.S */
7725    bl      common_abort
7726
7727
7728
7729    .balign 64
7730    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7731    .global dvmAsmInstructionEnd
7732dvmAsmInstructionEnd:
7733
7734/*
7735 * ===========================================================================
7736 *  Sister implementations
7737 * ===========================================================================
7738 */
7739    .global dvmAsmSisterStart
7740    .type   dvmAsmSisterStart, %function
7741    .text
7742    .balign 4
7743dvmAsmSisterStart:
7744
7745/* continuation for OP_CONST_STRING */
7746
7747    /*
7748     * Continuation if the String has not yet been resolved.
7749     *  r1: BBBB (String ref)
7750     *  r9: target register
7751     */
7752.LOP_CONST_STRING_resolve:
7753    EXPORT_PC()
7754    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7755    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7756    bl      dvmResolveString            @ r0<- String reference
7757    cmp     r0, #0                      @ failed?
7758    beq     common_exceptionThrown      @ yup, handle the exception
7759    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7761    SET_VREG(r0, r9)                    @ vAA<- r0
7762    GOTO_OPCODE(ip)                     @ jump to next instruction
7763
7764/* continuation for OP_CONST_STRING_JUMBO */
7765
7766    /*
7767     * Continuation if the String has not yet been resolved.
7768     *  r1: BBBBBBBB (String ref)
7769     *  r9: target register
7770     */
7771.LOP_CONST_STRING_JUMBO_resolve:
7772    EXPORT_PC()
7773    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7774    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7775    bl      dvmResolveString            @ r0<- String reference
7776    cmp     r0, #0                      @ failed?
7777    beq     common_exceptionThrown      @ yup, handle the exception
7778    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7779    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7780    SET_VREG(r0, r9)                    @ vAA<- r0
7781    GOTO_OPCODE(ip)                     @ jump to next instruction
7782
7783/* continuation for OP_CONST_CLASS */
7784
7785    /*
7786     * Continuation if the Class has not yet been resolved.
7787     *  r1: BBBB (Class ref)
7788     *  r9: target register
7789     */
7790.LOP_CONST_CLASS_resolve:
7791    EXPORT_PC()
7792    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7793    mov     r2, #1                      @ r2<- true
7794    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7795    bl      dvmResolveClass             @ r0<- Class reference
7796    cmp     r0, #0                      @ failed?
7797    beq     common_exceptionThrown      @ yup, handle the exception
7798    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7800    SET_VREG(r0, r9)                    @ vAA<- r0
7801    GOTO_OPCODE(ip)                     @ jump to next instruction
7802
7803/* continuation for OP_CHECK_CAST */
7804
7805    /*
7806     * Trivial test failed, need to perform full check.  This is common.
7807     *  r0 holds obj->clazz
7808     *  r1 holds class resolved from BBBB
7809     *  r9 holds object
7810     */
7811.LOP_CHECK_CAST_fullcheck:
7812    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7813    cmp     r0, #0                      @ failed?
7814    bne     .LOP_CHECK_CAST_okay            @ no, success
7815
7816    @ A cast has failed.  We need to throw a ClassCastException with the
7817    @ class of the object that failed to be cast.
7818    EXPORT_PC()                         @ about to throw
7819    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7820    ldr     r0, .LstrClassCastExceptionPtr
7821    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7822    bl      dvmThrowExceptionWithClassMessage
7823    b       common_exceptionThrown
7824
7825    /*
7826     * Resolution required.  This is the least-likely path.
7827     *
7828     *  r2 holds BBBB
7829     *  r9 holds object
7830     */
7831.LOP_CHECK_CAST_resolve:
7832    EXPORT_PC()                         @ resolve() could throw
7833    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7834    mov     r1, r2                      @ r1<- BBBB
7835    mov     r2, #0                      @ r2<- false
7836    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7837    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7838    cmp     r0, #0                      @ got null?
7839    beq     common_exceptionThrown      @ yes, handle exception
7840    mov     r1, r0                      @ r1<- class resolved from BBB
7841    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7842    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7843
7844.LstrClassCastExceptionPtr:
7845    .word   .LstrClassCastException
7846
7847/* continuation for OP_INSTANCE_OF */
7848
7849    /*
7850     * Trivial test failed, need to perform full check.  This is common.
7851     *  r0 holds obj->clazz
7852     *  r1 holds class resolved from BBBB
7853     *  r9 holds A
7854     */
7855.LOP_INSTANCE_OF_fullcheck:
7856    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7857    @ fall through to OP_INSTANCE_OF_store
7858
7859    /*
7860     * r0 holds boolean result
7861     * r9 holds A
7862     */
7863.LOP_INSTANCE_OF_store:
7864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7865    SET_VREG(r0, r9)                    @ vA<- r0
7866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7867    GOTO_OPCODE(ip)                     @ jump to next instruction
7868
7869    /*
7870     * Trivial test succeeded, save and bail.
7871     *  r9 holds A
7872     */
7873.LOP_INSTANCE_OF_trivial:
7874    mov     r0, #1                      @ indicate success
7875    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7876    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7877    SET_VREG(r0, r9)                    @ vA<- r0
7878    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7879    GOTO_OPCODE(ip)                     @ jump to next instruction
7880
7881    /*
7882     * Resolution required.  This is the least-likely path.
7883     *
7884     *  r3 holds BBBB
7885     *  r9 holds A
7886     */
7887.LOP_INSTANCE_OF_resolve:
7888    EXPORT_PC()                         @ resolve() could throw
7889    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7890    mov     r1, r3                      @ r1<- BBBB
7891    mov     r2, #1                      @ r2<- true
7892    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7893    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7894    cmp     r0, #0                      @ got null?
7895    beq     common_exceptionThrown      @ yes, handle exception
7896    mov     r1, r0                      @ r1<- class resolved from BBB
7897    mov     r3, rINST, lsr #12          @ r3<- B
7898    GET_VREG(r0, r3)                    @ r0<- vB (object)
7899    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7900    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7901
7902/* continuation for OP_NEW_INSTANCE */
7903
7904    .balign 32                          @ minimize cache lines
7905.LOP_NEW_INSTANCE_finish: @ r0=new object
7906    mov     r3, rINST, lsr #8           @ r3<- AA
7907    cmp     r0, #0                      @ failed?
7908    beq     common_exceptionThrown      @ yes, handle the exception
7909    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7911    SET_VREG(r0, r3)                    @ vAA<- r0
7912    GOTO_OPCODE(ip)                     @ jump to next instruction
7913
7914    /*
7915     * Class initialization required.
7916     *
7917     *  r0 holds class object
7918     */
7919.LOP_NEW_INSTANCE_needinit:
7920    mov     r9, r0                      @ save r0
7921    bl      dvmInitClass                @ initialize class
7922    cmp     r0, #0                      @ check boolean result
7923    mov     r0, r9                      @ restore r0
7924    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7925    b       common_exceptionThrown      @ failed, deal with init exception
7926
7927    /*
7928     * Resolution required.  This is the least-likely path.
7929     *
7930     *  r1 holds BBBB
7931     */
7932.LOP_NEW_INSTANCE_resolve:
7933    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7934    mov     r2, #0                      @ r2<- false
7935    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7936    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7937    cmp     r0, #0                      @ got null?
7938    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7939    b       common_exceptionThrown      @ yes, handle exception
7940
7941.LstrInstantiationErrorPtr:
7942    .word   .LstrInstantiationError
7943
7944/* continuation for OP_NEW_ARRAY */
7945
7946
7947    /*
7948     * Resolve class.  (This is an uncommon case.)
7949     *
7950     *  r1 holds array length
7951     *  r2 holds class ref CCCC
7952     */
7953.LOP_NEW_ARRAY_resolve:
7954    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7955    mov     r9, r1                      @ r9<- length (save)
7956    mov     r1, r2                      @ r1<- CCCC
7957    mov     r2, #0                      @ r2<- false
7958    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7959    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7960    cmp     r0, #0                      @ got null?
7961    mov     r1, r9                      @ r1<- length (restore)
7962    beq     common_exceptionThrown      @ yes, handle exception
7963    @ fall through to OP_NEW_ARRAY_finish
7964
7965    /*
7966     * Finish allocation.
7967     *
7968     *  r0 holds class
7969     *  r1 holds array length
7970     */
7971.LOP_NEW_ARRAY_finish:
7972    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7973    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7974    cmp     r0, #0                      @ failed?
7975    mov     r2, rINST, lsr #8           @ r2<- A+
7976    beq     common_exceptionThrown      @ yes, handle the exception
7977    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7978    and     r2, r2, #15                 @ r2<- A
7979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7980    SET_VREG(r0, r2)                    @ vA<- r0
7981    GOTO_OPCODE(ip)                     @ jump to next instruction
7982
7983/* continuation for OP_FILLED_NEW_ARRAY */
7984
7985    /*
7986     * On entry:
7987     *  r0 holds array class
7988     *  r10 holds AA or BA
7989     */
7990.LOP_FILLED_NEW_ARRAY_continue:
7991    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7992    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7993    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
7994    .if     0
7995    mov     r1, r10                     @ r1<- AA (length)
7996    .else
7997    mov     r1, r10, lsr #4             @ r1<- B (length)
7998    .endif
7999    cmp     rINST, #'I'                 @ array of ints?
8000    cmpne   rINST, #'L'                 @ array of objects?
8001    cmpne   rINST, #'['                 @ array of arrays?
8002    mov     r9, r1                      @ save length in r9
8003    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8004    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8005    cmp     r0, #0                      @ null return?
8006    beq     common_exceptionThrown      @ alloc failed, handle exception
8007
8008    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8009    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8010    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8011    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8012    subs    r9, r9, #1                  @ length--, check for neg
8013    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8014    bmi     2f                          @ was zero, bail
8015
8016    @ copy values from registers into the array
8017    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8018    .if     0
8019    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80201:  ldr     r3, [r2], #4                @ r3<- *r2++
8021    subs    r9, r9, #1                  @ count--
8022    str     r3, [r0], #4                @ *contents++ = vX
8023    bpl     1b
8024    @ continue at 2
8025    .else
8026    cmp     r9, #4                      @ length was initially 5?
8027    and     r2, r10, #15                @ r2<- A
8028    bne     1f                          @ <= 4 args, branch
8029    GET_VREG(r3, r2)                    @ r3<- vA
8030    sub     r9, r9, #1                  @ count--
8031    str     r3, [r0, #16]               @ contents[4] = vA
80321:  and     r2, r1, #15                 @ r2<- F/E/D/C
8033    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8034    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8035    subs    r9, r9, #1                  @ count--
8036    str     r3, [r0], #4                @ *contents++ = vX
8037    bpl     1b
8038    @ continue at 2
8039    .endif
8040
80412:
8042    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8043    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8044    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8045    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8046    cmp     r1, #'I'                         @ Is int array?
8047    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
8048    GOTO_OPCODE(ip)                          @ execute it
8049
8050    /*
8051     * Throw an exception indicating that we have not implemented this
8052     * mode of filled-new-array.
8053     */
8054.LOP_FILLED_NEW_ARRAY_notimpl:
8055    ldr     r0, .L_strInternalError
8056    ldr     r1, .L_strFilledNewArrayNotImpl
8057    bl      dvmThrowException
8058    b       common_exceptionThrown
8059
8060    .if     (!0)                 @ define in one or the other, not both
8061.L_strFilledNewArrayNotImpl:
8062    .word   .LstrFilledNewArrayNotImpl
8063.L_strInternalError:
8064    .word   .LstrInternalError
8065    .endif
8066
8067/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8068
8069    /*
8070     * On entry:
8071     *  r0 holds array class
8072     *  r10 holds AA or BA
8073     */
8074.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8075    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8076    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8077    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8078    .if     1
8079    mov     r1, r10                     @ r1<- AA (length)
8080    .else
8081    mov     r1, r10, lsr #4             @ r1<- B (length)
8082    .endif
8083    cmp     rINST, #'I'                 @ array of ints?
8084    cmpne   rINST, #'L'                 @ array of objects?
8085    cmpne   rINST, #'['                 @ array of arrays?
8086    mov     r9, r1                      @ save length in r9
8087    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8088    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8089    cmp     r0, #0                      @ null return?
8090    beq     common_exceptionThrown      @ alloc failed, handle exception
8091
8092    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8093    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8094    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8095    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8096    subs    r9, r9, #1                  @ length--, check for neg
8097    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8098    bmi     2f                          @ was zero, bail
8099
8100    @ copy values from registers into the array
8101    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8102    .if     1
8103    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81041:  ldr     r3, [r2], #4                @ r3<- *r2++
8105    subs    r9, r9, #1                  @ count--
8106    str     r3, [r0], #4                @ *contents++ = vX
8107    bpl     1b
8108    @ continue at 2
8109    .else
8110    cmp     r9, #4                      @ length was initially 5?
8111    and     r2, r10, #15                @ r2<- A
8112    bne     1f                          @ <= 4 args, branch
8113    GET_VREG(r3, r2)                    @ r3<- vA
8114    sub     r9, r9, #1                  @ count--
8115    str     r3, [r0, #16]               @ contents[4] = vA
81161:  and     r2, r1, #15                 @ r2<- F/E/D/C
8117    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8118    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8119    subs    r9, r9, #1                  @ count--
8120    str     r3, [r0], #4                @ *contents++ = vX
8121    bpl     1b
8122    @ continue at 2
8123    .endif
8124
81252:
8126    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8127    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8128    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8129    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8130    cmp     r1, #'I'                         @ Is int array?
8131    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
8132    GOTO_OPCODE(ip)                          @ execute it
8133
8134    /*
8135     * Throw an exception indicating that we have not implemented this
8136     * mode of filled-new-array.
8137     */
8138.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8139    ldr     r0, .L_strInternalError
8140    ldr     r1, .L_strFilledNewArrayNotImpl
8141    bl      dvmThrowException
8142    b       common_exceptionThrown
8143
8144    .if     (!1)                 @ define in one or the other, not both
8145.L_strFilledNewArrayNotImpl:
8146    .word   .LstrFilledNewArrayNotImpl
8147.L_strInternalError:
8148    .word   .LstrInternalError
8149    .endif
8150
8151/* continuation for OP_CMPL_FLOAT */
8152.LOP_CMPL_FLOAT_finish:
8153    SET_VREG(r0, r9)                    @ vAA<- r0
8154    GOTO_OPCODE(ip)                     @ jump to next instruction
8155
8156/* continuation for OP_CMPG_FLOAT */
8157.LOP_CMPG_FLOAT_finish:
8158    SET_VREG(r0, r9)                    @ vAA<- r0
8159    GOTO_OPCODE(ip)                     @ jump to next instruction
8160
8161/* continuation for OP_CMPL_DOUBLE */
8162.LOP_CMPL_DOUBLE_finish:
8163    SET_VREG(r0, r9)                    @ vAA<- r0
8164    GOTO_OPCODE(ip)                     @ jump to next instruction
8165
8166/* continuation for OP_CMPG_DOUBLE */
8167.LOP_CMPG_DOUBLE_finish:
8168    SET_VREG(r0, r9)                    @ vAA<- r0
8169    GOTO_OPCODE(ip)                     @ jump to next instruction
8170
8171/* continuation for OP_CMP_LONG */
8172
8173.LOP_CMP_LONG_less:
8174    mvn     r1, #0                      @ r1<- -1
8175    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8176    @ instead, we just replicate the tail end.
8177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8178    SET_VREG(r1, r9)                    @ vAA<- r1
8179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8180    GOTO_OPCODE(ip)                     @ jump to next instruction
8181
8182.LOP_CMP_LONG_greater:
8183    mov     r1, #1                      @ r1<- 1
8184    @ fall through to _finish
8185
8186.LOP_CMP_LONG_finish:
8187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8188    SET_VREG(r1, r9)                    @ vAA<- r1
8189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8190    GOTO_OPCODE(ip)                     @ jump to next instruction
8191
8192/* continuation for OP_AGET_WIDE */
8193
8194.LOP_AGET_WIDE_finish:
8195    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8196    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8197    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8198    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8199    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8200    GOTO_OPCODE(ip)                     @ jump to next instruction
8201
8202/* continuation for OP_APUT_WIDE */
8203
8204.LOP_APUT_WIDE_finish:
8205    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8206    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8208    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8209    GOTO_OPCODE(ip)                     @ jump to next instruction
8210
8211/* continuation for OP_APUT_OBJECT */
8212    /*
8213     * On entry:
8214     *  r1 = vBB (arrayObj)
8215     *  r9 = vAA (obj)
8216     *  r10 = offset into array (vBB + vCC * width)
8217     */
8218.LOP_APUT_OBJECT_finish:
8219    cmp     r9, #0                      @ storing null reference?
8220    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8221    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8222    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8223    bl      dvmCanPutArrayElement       @ test object type vs. array type
8224    cmp     r0, #0                      @ okay?
8225    beq     common_errArrayStore        @ no
8226    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8227    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8228    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8230    str     r9, [r10]                   @ vBB[vCC]<- vAA
8231    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
8232    GOTO_OPCODE(ip)                     @ jump to next instruction
8233.LOP_APUT_OBJECT_skip_check:
8234    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8236    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8237    GOTO_OPCODE(ip)                     @ jump to next instruction
8238
8239/* continuation for OP_IGET */
8240
8241    /*
8242     * Currently:
8243     *  r0 holds resolved field
8244     *  r9 holds object
8245     */
8246.LOP_IGET_finish:
8247    @bl      common_squeak0
8248    cmp     r9, #0                      @ check object for null
8249    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8250    beq     common_errNullObject        @ object was null
8251    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8252    ubfx    r2, rINST, #8, #4           @ r2<- A
8253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8254    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8255    SET_VREG(r0, r2)                    @ fp[A]<- r0
8256    GOTO_OPCODE(ip)                     @ jump to next instruction
8257
8258/* continuation for OP_IGET_WIDE */
8259
8260    /*
8261     * Currently:
8262     *  r0 holds resolved field
8263     *  r9 holds object
8264     */
8265.LOP_IGET_WIDE_finish:
8266    cmp     r9, #0                      @ check object for null
8267    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8268    beq     common_errNullObject        @ object was null
8269    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8270    ubfx    r2, rINST, #8, #4           @ r2<- A
8271    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8272    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8273    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8274    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8275    GOTO_OPCODE(ip)                     @ jump to next instruction
8276
8277/* continuation for OP_IGET_OBJECT */
8278
8279    /*
8280     * Currently:
8281     *  r0 holds resolved field
8282     *  r9 holds object
8283     */
8284.LOP_IGET_OBJECT_finish:
8285    @bl      common_squeak0
8286    cmp     r9, #0                      @ check object for null
8287    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8288    beq     common_errNullObject        @ object was null
8289    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8290    @ no-op                             @ acquiring load
8291    mov     r2, rINST, lsr #8           @ r2<- A+
8292    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8293    and     r2, r2, #15                 @ r2<- A
8294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8295    SET_VREG(r0, r2)                    @ fp[A]<- r0
8296    GOTO_OPCODE(ip)                     @ jump to next instruction
8297
8298/* continuation for OP_IGET_BOOLEAN */
8299
8300    /*
8301     * Currently:
8302     *  r0 holds resolved field
8303     *  r9 holds object
8304     */
8305.LOP_IGET_BOOLEAN_finish:
8306    @bl      common_squeak1
8307    cmp     r9, #0                      @ check object for null
8308    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8309    beq     common_errNullObject        @ object was null
8310    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8311    @ no-op                             @ acquiring load
8312    mov     r2, rINST, lsr #8           @ r2<- A+
8313    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8314    and     r2, r2, #15                 @ r2<- A
8315    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8316    SET_VREG(r0, r2)                    @ fp[A]<- r0
8317    GOTO_OPCODE(ip)                     @ jump to next instruction
8318
8319/* continuation for OP_IGET_BYTE */
8320
8321    /*
8322     * Currently:
8323     *  r0 holds resolved field
8324     *  r9 holds object
8325     */
8326.LOP_IGET_BYTE_finish:
8327    @bl      common_squeak2
8328    cmp     r9, #0                      @ check object for null
8329    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8330    beq     common_errNullObject        @ object was null
8331    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8332    @ no-op                             @ acquiring load
8333    mov     r2, rINST, lsr #8           @ r2<- A+
8334    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8335    and     r2, r2, #15                 @ r2<- A
8336    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8337    SET_VREG(r0, r2)                    @ fp[A]<- r0
8338    GOTO_OPCODE(ip)                     @ jump to next instruction
8339
8340/* continuation for OP_IGET_CHAR */
8341
8342    /*
8343     * Currently:
8344     *  r0 holds resolved field
8345     *  r9 holds object
8346     */
8347.LOP_IGET_CHAR_finish:
8348    @bl      common_squeak3
8349    cmp     r9, #0                      @ check object for null
8350    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8351    beq     common_errNullObject        @ object was null
8352    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8353    @ no-op                             @ acquiring load
8354    mov     r2, rINST, lsr #8           @ r2<- A+
8355    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8356    and     r2, r2, #15                 @ r2<- A
8357    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8358    SET_VREG(r0, r2)                    @ fp[A]<- r0
8359    GOTO_OPCODE(ip)                     @ jump to next instruction
8360
8361/* continuation for OP_IGET_SHORT */
8362
8363    /*
8364     * Currently:
8365     *  r0 holds resolved field
8366     *  r9 holds object
8367     */
8368.LOP_IGET_SHORT_finish:
8369    @bl      common_squeak4
8370    cmp     r9, #0                      @ check object for null
8371    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8372    beq     common_errNullObject        @ object was null
8373    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8374    @ no-op                             @ acquiring load
8375    mov     r2, rINST, lsr #8           @ r2<- A+
8376    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8377    and     r2, r2, #15                 @ r2<- A
8378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8379    SET_VREG(r0, r2)                    @ fp[A]<- r0
8380    GOTO_OPCODE(ip)                     @ jump to next instruction
8381
8382/* continuation for OP_IPUT */
8383
8384    /*
8385     * Currently:
8386     *  r0 holds resolved field
8387     *  r9 holds object
8388     */
8389.LOP_IPUT_finish:
8390    @bl      common_squeak0
8391    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8392    ubfx    r1, rINST, #8, #4           @ r1<- A
8393    cmp     r9, #0                      @ check object for null
8394    GET_VREG(r0, r1)                    @ r0<- fp[A]
8395    beq     common_errNullObject        @ object was null
8396    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8397    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8398    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8399    GOTO_OPCODE(ip)                     @ jump to next instruction
8400
8401/* continuation for OP_IPUT_WIDE */
8402
8403    /*
8404     * Currently:
8405     *  r0 holds resolved field
8406     *  r9 holds object
8407     */
8408.LOP_IPUT_WIDE_finish:
8409    ubfx    r2, rINST, #8, #4           @ r2<- A
8410    cmp     r9, #0                      @ check object for null
8411    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8412    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8413    beq     common_errNullObject        @ object was null
8414    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8415    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8416    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8417    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8418    GOTO_OPCODE(ip)                     @ jump to next instruction
8419
8420/* continuation for OP_IPUT_OBJECT */
8421
8422    /*
8423     * Currently:
8424     *  r0 holds resolved field
8425     *  r9 holds object
8426     */
8427.LOP_IPUT_OBJECT_finish:
8428    @bl      common_squeak0
8429    mov     r1, rINST, lsr #8           @ r1<- A+
8430    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8431    and     r1, r1, #15                 @ r1<- A
8432    cmp     r9, #0                      @ check object for null
8433    GET_VREG(r0, r1)                    @ r0<- fp[A]
8434    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8435    beq     common_errNullObject        @ object was null
8436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8437    add     r9, r3                      @ r9<- direct ptr to target location
8438    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8439    @ no-op                             @ releasing store
8440    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
8441    cmp     r0, #0                      @ stored a null reference?
8442    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8443    GOTO_OPCODE(ip)                     @ jump to next instruction
8444
8445/* continuation for OP_IPUT_BOOLEAN */
8446
8447    /*
8448     * Currently:
8449     *  r0 holds resolved field
8450     *  r9 holds object
8451     */
8452.LOP_IPUT_BOOLEAN_finish:
8453    @bl      common_squeak1
8454    mov     r1, rINST, lsr #8           @ r1<- A+
8455    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8456    and     r1, r1, #15                 @ r1<- A
8457    cmp     r9, #0                      @ check object for null
8458    GET_VREG(r0, r1)                    @ r0<- fp[A]
8459    beq     common_errNullObject        @ object was null
8460    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8461    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8462    @ no-op                             @ releasing store
8463    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8464    GOTO_OPCODE(ip)                     @ jump to next instruction
8465
8466/* continuation for OP_IPUT_BYTE */
8467
8468    /*
8469     * Currently:
8470     *  r0 holds resolved field
8471     *  r9 holds object
8472     */
8473.LOP_IPUT_BYTE_finish:
8474    @bl      common_squeak2
8475    mov     r1, rINST, lsr #8           @ r1<- A+
8476    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8477    and     r1, r1, #15                 @ r1<- A
8478    cmp     r9, #0                      @ check object for null
8479    GET_VREG(r0, r1)                    @ r0<- fp[A]
8480    beq     common_errNullObject        @ object was null
8481    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8482    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8483    @ no-op                             @ releasing store
8484    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8485    GOTO_OPCODE(ip)                     @ jump to next instruction
8486
8487/* continuation for OP_IPUT_CHAR */
8488
8489    /*
8490     * Currently:
8491     *  r0 holds resolved field
8492     *  r9 holds object
8493     */
8494.LOP_IPUT_CHAR_finish:
8495    @bl      common_squeak3
8496    mov     r1, rINST, lsr #8           @ r1<- A+
8497    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8498    and     r1, r1, #15                 @ r1<- A
8499    cmp     r9, #0                      @ check object for null
8500    GET_VREG(r0, r1)                    @ r0<- fp[A]
8501    beq     common_errNullObject        @ object was null
8502    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8504    @ no-op                             @ releasing store
8505    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8506    GOTO_OPCODE(ip)                     @ jump to next instruction
8507
8508/* continuation for OP_IPUT_SHORT */
8509
8510    /*
8511     * Currently:
8512     *  r0 holds resolved field
8513     *  r9 holds object
8514     */
8515.LOP_IPUT_SHORT_finish:
8516    @bl      common_squeak4
8517    mov     r1, rINST, lsr #8           @ r1<- A+
8518    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8519    and     r1, r1, #15                 @ r1<- A
8520    cmp     r9, #0                      @ check object for null
8521    GET_VREG(r0, r1)                    @ r0<- fp[A]
8522    beq     common_errNullObject        @ object was null
8523    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8524    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8525    @ no-op                             @ releasing store
8526    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8527    GOTO_OPCODE(ip)                     @ jump to next instruction
8528
8529/* continuation for OP_SGET */
8530
8531    /*
8532     * Continuation if the field has not yet been resolved.
8533     *  r1: BBBB field ref
8534     */
8535.LOP_SGET_resolve:
8536    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8537    EXPORT_PC()                         @ resolve() could throw, so export now
8538    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8539    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8540    cmp     r0, #0                      @ success?
8541    bne     .LOP_SGET_finish          @ yes, finish
8542    b       common_exceptionThrown      @ no, handle exception
8543
8544/* continuation for OP_SGET_WIDE */
8545
8546    /*
8547     * Continuation if the field has not yet been resolved.
8548     *  r1: BBBB field ref
8549     *
8550     * Returns StaticField pointer in r0.
8551     */
8552.LOP_SGET_WIDE_resolve:
8553    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8554    EXPORT_PC()                         @ resolve() could throw, so export now
8555    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8556    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8557    cmp     r0, #0                      @ success?
8558    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8559    b       common_exceptionThrown      @ no, handle exception
8560
8561/* continuation for OP_SGET_OBJECT */
8562
8563    /*
8564     * Continuation if the field has not yet been resolved.
8565     *  r1: BBBB field ref
8566     */
8567.LOP_SGET_OBJECT_resolve:
8568    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8569    EXPORT_PC()                         @ resolve() could throw, so export now
8570    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8571    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8572    cmp     r0, #0                      @ success?
8573    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8574    b       common_exceptionThrown      @ no, handle exception
8575
8576/* continuation for OP_SGET_BOOLEAN */
8577
8578    /*
8579     * Continuation if the field has not yet been resolved.
8580     *  r1: BBBB field ref
8581     */
8582.LOP_SGET_BOOLEAN_resolve:
8583    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8584    EXPORT_PC()                         @ resolve() could throw, so export now
8585    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8586    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8587    cmp     r0, #0                      @ success?
8588    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8589    b       common_exceptionThrown      @ no, handle exception
8590
8591/* continuation for OP_SGET_BYTE */
8592
8593    /*
8594     * Continuation if the field has not yet been resolved.
8595     *  r1: BBBB field ref
8596     */
8597.LOP_SGET_BYTE_resolve:
8598    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8599    EXPORT_PC()                         @ resolve() could throw, so export now
8600    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8601    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8602    cmp     r0, #0                      @ success?
8603    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8604    b       common_exceptionThrown      @ no, handle exception
8605
8606/* continuation for OP_SGET_CHAR */
8607
8608    /*
8609     * Continuation if the field has not yet been resolved.
8610     *  r1: BBBB field ref
8611     */
8612.LOP_SGET_CHAR_resolve:
8613    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8614    EXPORT_PC()                         @ resolve() could throw, so export now
8615    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8616    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8617    cmp     r0, #0                      @ success?
8618    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8619    b       common_exceptionThrown      @ no, handle exception
8620
8621/* continuation for OP_SGET_SHORT */
8622
8623    /*
8624     * Continuation if the field has not yet been resolved.
8625     *  r1: BBBB field ref
8626     */
8627.LOP_SGET_SHORT_resolve:
8628    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8629    EXPORT_PC()                         @ resolve() could throw, so export now
8630    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8631    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8632    cmp     r0, #0                      @ success?
8633    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8634    b       common_exceptionThrown      @ no, handle exception
8635
8636/* continuation for OP_SPUT */
8637
8638    /*
8639     * Continuation if the field has not yet been resolved.
8640     *  r1: BBBB field ref
8641     */
8642.LOP_SPUT_resolve:
8643    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8644    EXPORT_PC()                         @ resolve() could throw, so export now
8645    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8646    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8647    cmp     r0, #0                      @ success?
8648    bne     .LOP_SPUT_finish          @ yes, finish
8649    b       common_exceptionThrown      @ no, handle exception
8650
8651/* continuation for OP_SPUT_WIDE */
8652
8653    /*
8654     * Continuation if the field has not yet been resolved.
8655     *  r1: BBBB field ref
8656     *  r9: &fp[AA]
8657     *
8658     * Returns StaticField pointer in r2.
8659     */
8660.LOP_SPUT_WIDE_resolve:
8661    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8662    EXPORT_PC()                         @ resolve() could throw, so export now
8663    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8664    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8665    cmp     r0, #0                      @ success?
8666    mov     r2, r0                      @ copy to r2
8667    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8668    b       common_exceptionThrown      @ no, handle exception
8669
8670/* continuation for OP_SPUT_OBJECT */
8671.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8672    mov     r2, rINST, lsr #8           @ r2<- AA
8673    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8674    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8675    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8677    add     r0, #offStaticField_value   @ r0<- pointer to store target
8678    @ no-op                             @ releasing store
8679    str     r1, [r0]                    @ field<- vAA
8680    cmp     r1, #0                      @ stored a null object?
8681    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
8682    GOTO_OPCODE(ip)                     @ jump to next instruction
8683
8684/* continuation for OP_SPUT_BOOLEAN */
8685
8686    /*
8687     * Continuation if the field has not yet been resolved.
8688     *  r1: BBBB field ref
8689     */
8690.LOP_SPUT_BOOLEAN_resolve:
8691    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8692    EXPORT_PC()                         @ resolve() could throw, so export now
8693    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8694    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8695    cmp     r0, #0                      @ success?
8696    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8697    b       common_exceptionThrown      @ no, handle exception
8698
8699/* continuation for OP_SPUT_BYTE */
8700
8701    /*
8702     * Continuation if the field has not yet been resolved.
8703     *  r1: BBBB field ref
8704     */
8705.LOP_SPUT_BYTE_resolve:
8706    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8707    EXPORT_PC()                         @ resolve() could throw, so export now
8708    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8709    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8710    cmp     r0, #0                      @ success?
8711    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8712    b       common_exceptionThrown      @ no, handle exception
8713
8714/* continuation for OP_SPUT_CHAR */
8715
8716    /*
8717     * Continuation if the field has not yet been resolved.
8718     *  r1: BBBB field ref
8719     */
8720.LOP_SPUT_CHAR_resolve:
8721    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8722    EXPORT_PC()                         @ resolve() could throw, so export now
8723    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8724    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8725    cmp     r0, #0                      @ success?
8726    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8727    b       common_exceptionThrown      @ no, handle exception
8728
8729/* continuation for OP_SPUT_SHORT */
8730
8731    /*
8732     * Continuation if the field has not yet been resolved.
8733     *  r1: BBBB field ref
8734     */
8735.LOP_SPUT_SHORT_resolve:
8736    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8737    EXPORT_PC()                         @ resolve() could throw, so export now
8738    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8739    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8740    cmp     r0, #0                      @ success?
8741    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8742    b       common_exceptionThrown      @ no, handle exception
8743
8744/* continuation for OP_INVOKE_VIRTUAL */
8745
8746    /*
8747     * At this point:
8748     *  r0 = resolved base method
8749     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8750     */
8751.LOP_INVOKE_VIRTUAL_continue:
8752    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8753    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8754    cmp     r1, #0                      @ is "this" null?
8755    beq     common_errNullObject        @ null "this", throw exception
8756    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8757    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8758    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8759    bl      common_invokeMethodNoRange @ continue on
8760
8761/* continuation for OP_INVOKE_SUPER */
8762
8763    /*
8764     * At this point:
8765     *  r0 = resolved base method
8766     *  r9 = method->clazz
8767     */
8768.LOP_INVOKE_SUPER_continue:
8769    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8770    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8771    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8772    EXPORT_PC()                         @ must export for invoke
8773    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8774    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8775    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8776    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8777    bl      common_invokeMethodNoRange @ continue on
8778
8779.LOP_INVOKE_SUPER_resolve:
8780    mov     r0, r9                      @ r0<- method->clazz
8781    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8782    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8783    cmp     r0, #0                      @ got null?
8784    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8785    b       common_exceptionThrown      @ yes, handle exception
8786
8787    /*
8788     * Throw a NoSuchMethodError with the method name as the message.
8789     *  r0 = resolved base method
8790     */
8791.LOP_INVOKE_SUPER_nsm:
8792    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8793    b       common_errNoSuchMethod
8794
8795/* continuation for OP_INVOKE_DIRECT */
8796
8797    /*
8798     * On entry:
8799     *  r1 = reference (BBBB or CCCC)
8800     *  r10 = "this" register
8801     */
8802.LOP_INVOKE_DIRECT_resolve:
8803    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8804    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8805    mov     r2, #METHOD_DIRECT          @ resolver method type
8806    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8807    cmp     r0, #0                      @ got null?
8808    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8809    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8810    b       common_exceptionThrown      @ yes, handle exception
8811
8812/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8813
8814    /*
8815     * At this point:
8816     *  r0 = resolved base method
8817     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8818     */
8819.LOP_INVOKE_VIRTUAL_RANGE_continue:
8820    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8821    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8822    cmp     r1, #0                      @ is "this" null?
8823    beq     common_errNullObject        @ null "this", throw exception
8824    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8825    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8826    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8827    bl      common_invokeMethodRange @ continue on
8828
8829/* continuation for OP_INVOKE_SUPER_RANGE */
8830
8831    /*
8832     * At this point:
8833     *  r0 = resolved base method
8834     *  r9 = method->clazz
8835     */
8836.LOP_INVOKE_SUPER_RANGE_continue:
8837    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8838    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8839    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8840    EXPORT_PC()                         @ must export for invoke
8841    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8842    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8843    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8844    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8845    bl      common_invokeMethodRange @ continue on
8846
8847.LOP_INVOKE_SUPER_RANGE_resolve:
8848    mov     r0, r9                      @ r0<- method->clazz
8849    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8850    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8851    cmp     r0, #0                      @ got null?
8852    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8853    b       common_exceptionThrown      @ yes, handle exception
8854
8855    /*
8856     * Throw a NoSuchMethodError with the method name as the message.
8857     *  r0 = resolved base method
8858     */
8859.LOP_INVOKE_SUPER_RANGE_nsm:
8860    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8861    b       common_errNoSuchMethod
8862
8863/* continuation for OP_INVOKE_DIRECT_RANGE */
8864
8865    /*
8866     * On entry:
8867     *  r1 = reference (BBBB or CCCC)
8868     *  r10 = "this" register
8869     */
8870.LOP_INVOKE_DIRECT_RANGE_resolve:
8871    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8872    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8873    mov     r2, #METHOD_DIRECT          @ resolver method type
8874    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8875    cmp     r0, #0                      @ got null?
8876    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8877    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8878    b       common_exceptionThrown      @ yes, handle exception
8879
8880/* continuation for OP_FLOAT_TO_LONG */
8881/*
8882 * Convert the float in r0 to a long in r0/r1.
8883 *
8884 * We have to clip values to long min/max per the specification.  The
8885 * expected common case is a "reasonable" value that converts directly
8886 * to modest integer.  The EABI convert function isn't doing this for us.
8887 */
8888f2l_doconv:
8889    stmfd   sp!, {r4, lr}
8890    mov     r1, #0x5f000000             @ (float)maxlong
8891    mov     r4, r0
8892    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8893    cmp     r0, #0                      @ nonzero == yes
8894    mvnne   r0, #0                      @ return maxlong (7fffffff)
8895    mvnne   r1, #0x80000000
8896    ldmnefd sp!, {r4, pc}
8897
8898    mov     r0, r4                      @ recover arg
8899    mov     r1, #0xdf000000             @ (float)minlong
8900    bl      __aeabi_fcmple              @ is arg <= minlong?
8901    cmp     r0, #0                      @ nonzero == yes
8902    movne   r0, #0                      @ return minlong (80000000)
8903    movne   r1, #0x80000000
8904    ldmnefd sp!, {r4, pc}
8905
8906    mov     r0, r4                      @ recover arg
8907    mov     r1, r4
8908    bl      __aeabi_fcmpeq              @ is arg == self?
8909    cmp     r0, #0                      @ zero == no
8910    moveq   r1, #0                      @ return zero for NaN
8911    ldmeqfd sp!, {r4, pc}
8912
8913    mov     r0, r4                      @ recover arg
8914    bl      __aeabi_f2lz                @ convert float to long
8915    ldmfd   sp!, {r4, pc}
8916
8917/* continuation for OP_DOUBLE_TO_LONG */
8918/*
8919 * Convert the double in r0/r1 to a long in r0/r1.
8920 *
8921 * We have to clip values to long min/max per the specification.  The
8922 * expected common case is a "reasonable" value that converts directly
8923 * to modest integer.  The EABI convert function isn't doing this for us.
8924 */
8925d2l_doconv:
8926    stmfd   sp!, {r4, r5, lr}           @ save regs
8927    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8928    add     r3, #0x00e00000             @  0x43e00000
8929    mov     r2, #0                      @ maxlong, as a double (low word)
8930    sub     sp, sp, #4                  @ align for EABI
8931    mov     r4, r0                      @ save a copy of r0
8932    mov     r5, r1                      @  and r1
8933    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8934    cmp     r0, #0                      @ nonzero == yes
8935    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8936    mvnne   r1, #0x80000000
8937    bne     1f
8938
8939    mov     r0, r4                      @ recover arg
8940    mov     r1, r5
8941    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8942    add     r3, #0x00e00000             @  0xc3e00000
8943    mov     r2, #0                      @ minlong, as a double (low word)
8944    bl      __aeabi_dcmple              @ is arg <= minlong?
8945    cmp     r0, #0                      @ nonzero == yes
8946    movne   r0, #0                      @ return minlong (8000000000000000)
8947    movne   r1, #0x80000000
8948    bne     1f
8949
8950    mov     r0, r4                      @ recover arg
8951    mov     r1, r5
8952    mov     r2, r4                      @ compare against self
8953    mov     r3, r5
8954    bl      __aeabi_dcmpeq              @ is arg == self?
8955    cmp     r0, #0                      @ zero == no
8956    moveq   r1, #0                      @ return zero for NaN
8957    beq     1f
8958
8959    mov     r0, r4                      @ recover arg
8960    mov     r1, r5
8961    bl      __aeabi_d2lz                @ convert double to long
8962
89631:
8964    add     sp, sp, #4
8965    ldmfd   sp!, {r4, r5, pc}
8966
8967/* continuation for OP_MUL_LONG */
8968
8969.LOP_MUL_LONG_finish:
8970    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8971    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8972    GOTO_OPCODE(ip)                     @ jump to next instruction
8973
8974/* continuation for OP_SHL_LONG */
8975
8976.LOP_SHL_LONG_finish:
8977    mov     r0, r0, asl r2              @  r0<- r0 << r2
8978    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8979    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8980    GOTO_OPCODE(ip)                     @ jump to next instruction
8981
8982/* continuation for OP_SHR_LONG */
8983
8984.LOP_SHR_LONG_finish:
8985    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8987    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8988    GOTO_OPCODE(ip)                     @ jump to next instruction
8989
8990/* continuation for OP_USHR_LONG */
8991
8992.LOP_USHR_LONG_finish:
8993    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8994    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8995    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8996    GOTO_OPCODE(ip)                     @ jump to next instruction
8997
8998/* continuation for OP_SHL_LONG_2ADDR */
8999
9000.LOP_SHL_LONG_2ADDR_finish:
9001    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9002    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9003    GOTO_OPCODE(ip)                     @ jump to next instruction
9004
9005/* continuation for OP_SHR_LONG_2ADDR */
9006
9007.LOP_SHR_LONG_2ADDR_finish:
9008    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9009    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9010    GOTO_OPCODE(ip)                     @ jump to next instruction
9011
9012/* continuation for OP_USHR_LONG_2ADDR */
9013
9014.LOP_USHR_LONG_2ADDR_finish:
9015    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9016    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9017    GOTO_OPCODE(ip)                     @ jump to next instruction
9018
9019/* continuation for OP_IGET_VOLATILE */
9020
9021    /*
9022     * Currently:
9023     *  r0 holds resolved field
9024     *  r9 holds object
9025     */
9026.LOP_IGET_VOLATILE_finish:
9027    @bl      common_squeak0
9028    cmp     r9, #0                      @ check object for null
9029    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9030    beq     common_errNullObject        @ object was null
9031    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9032    SMP_DMB                            @ acquiring load
9033    mov     r2, rINST, lsr #8           @ r2<- A+
9034    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9035    and     r2, r2, #15                 @ r2<- A
9036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9037    SET_VREG(r0, r2)                    @ fp[A]<- r0
9038    GOTO_OPCODE(ip)                     @ jump to next instruction
9039
9040/* continuation for OP_IPUT_VOLATILE */
9041
9042    /*
9043     * Currently:
9044     *  r0 holds resolved field
9045     *  r9 holds object
9046     */
9047.LOP_IPUT_VOLATILE_finish:
9048    @bl      common_squeak0
9049    mov     r1, rINST, lsr #8           @ r1<- A+
9050    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9051    and     r1, r1, #15                 @ r1<- A
9052    cmp     r9, #0                      @ check object for null
9053    GET_VREG(r0, r1)                    @ r0<- fp[A]
9054    beq     common_errNullObject        @ object was null
9055    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9056    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9057    SMP_DMB                            @ releasing store
9058    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9059    GOTO_OPCODE(ip)                     @ jump to next instruction
9060
9061/* continuation for OP_SGET_VOLATILE */
9062
9063    /*
9064     * Continuation if the field has not yet been resolved.
9065     *  r1: BBBB field ref
9066     */
9067.LOP_SGET_VOLATILE_resolve:
9068    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9069    EXPORT_PC()                         @ resolve() could throw, so export now
9070    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9071    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9072    cmp     r0, #0                      @ success?
9073    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9074    b       common_exceptionThrown      @ no, handle exception
9075
9076/* continuation for OP_SPUT_VOLATILE */
9077
9078    /*
9079     * Continuation if the field has not yet been resolved.
9080     *  r1: BBBB field ref
9081     */
9082.LOP_SPUT_VOLATILE_resolve:
9083    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9084    EXPORT_PC()                         @ resolve() could throw, so export now
9085    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9086    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9087    cmp     r0, #0                      @ success?
9088    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9089    b       common_exceptionThrown      @ no, handle exception
9090
9091/* continuation for OP_IGET_OBJECT_VOLATILE */
9092
9093    /*
9094     * Currently:
9095     *  r0 holds resolved field
9096     *  r9 holds object
9097     */
9098.LOP_IGET_OBJECT_VOLATILE_finish:
9099    @bl      common_squeak0
9100    cmp     r9, #0                      @ check object for null
9101    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9102    beq     common_errNullObject        @ object was null
9103    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9104    SMP_DMB                            @ acquiring load
9105    mov     r2, rINST, lsr #8           @ r2<- A+
9106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9107    and     r2, r2, #15                 @ r2<- A
9108    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9109    SET_VREG(r0, r2)                    @ fp[A]<- r0
9110    GOTO_OPCODE(ip)                     @ jump to next instruction
9111
9112/* continuation for OP_IGET_WIDE_VOLATILE */
9113
9114    /*
9115     * Currently:
9116     *  r0 holds resolved field
9117     *  r9 holds object
9118     */
9119.LOP_IGET_WIDE_VOLATILE_finish:
9120    cmp     r9, #0                      @ check object for null
9121    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9122    beq     common_errNullObject        @ object was null
9123    .if     1
9124    add     r0, r9, r3                  @ r0<- address of field
9125    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9126    .else
9127    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9128    .endif
9129    mov     r2, rINST, lsr #8           @ r2<- A+
9130    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9131    and     r2, r2, #15                 @ r2<- A
9132    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9134    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9135    GOTO_OPCODE(ip)                     @ jump to next instruction
9136
9137/* continuation for OP_IPUT_WIDE_VOLATILE */
9138
9139    /*
9140     * Currently:
9141     *  r0 holds resolved field
9142     *  r9 holds object
9143     */
9144.LOP_IPUT_WIDE_VOLATILE_finish:
9145    mov     r2, rINST, lsr #8           @ r2<- A+
9146    cmp     r9, #0                      @ check object for null
9147    and     r2, r2, #15                 @ r2<- A
9148    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9149    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9150    beq     common_errNullObject        @ object was null
9151    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9152    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9153    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9154    .if     1
9155    add     r2, r9, r3                  @ r2<- target address
9156    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9157    .else
9158    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9159    .endif
9160    GOTO_OPCODE(r10)                    @ jump to next instruction
9161
9162/* continuation for OP_SGET_WIDE_VOLATILE */
9163
9164    /*
9165     * Continuation if the field has not yet been resolved.
9166     *  r1: BBBB field ref
9167     *
9168     * Returns StaticField pointer in r0.
9169     */
9170.LOP_SGET_WIDE_VOLATILE_resolve:
9171    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9172    EXPORT_PC()                         @ resolve() could throw, so export now
9173    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9174    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9175    cmp     r0, #0                      @ success?
9176    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9177    b       common_exceptionThrown      @ no, handle exception
9178
9179/* continuation for OP_SPUT_WIDE_VOLATILE */
9180
9181    /*
9182     * Continuation if the field has not yet been resolved.
9183     *  r1: BBBB field ref
9184     *  r9: &fp[AA]
9185     *
9186     * Returns StaticField pointer in r2.
9187     */
9188.LOP_SPUT_WIDE_VOLATILE_resolve:
9189    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9190    EXPORT_PC()                         @ resolve() could throw, so export now
9191    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9192    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9193    cmp     r0, #0                      @ success?
9194    mov     r2, r0                      @ copy to r2
9195    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9196    b       common_exceptionThrown      @ no, handle exception
9197
9198/* continuation for OP_EXECUTE_INLINE */
9199
9200    /*
9201     * Extract args, call function.
9202     *  r0 = #of args (0-4)
9203     *  r10 = call index
9204     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9205     *
9206     * Other ideas:
9207     * - Use a jump table from the main piece to jump directly into the
9208     *   AND/LDR pairs.  Costs a data load, saves a branch.
9209     * - Have five separate pieces that do the loading, so we can work the
9210     *   interleave a little better.  Increases code size.
9211     */
9212.LOP_EXECUTE_INLINE_continue:
9213    rsb     r0, r0, #4                  @ r0<- 4-r0
9214    FETCH(r9, 2)                        @ r9<- FEDC
9215    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9216    bl      common_abort                @ (skipped due to ARM prefetch)
92174:  and     ip, r9, #0xf000             @ isolate F
9218    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92193:  and     ip, r9, #0x0f00             @ isolate E
9220    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92212:  and     ip, r9, #0x00f0             @ isolate D
9222    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92231:  and     ip, r9, #0x000f             @ isolate C
9224    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92250:
9226    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9227    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9228    @ (not reached)
9229
9230.LOP_EXECUTE_INLINE_table:
9231    .word   gDvmInlineOpsTable
9232
9233/* continuation for OP_EXECUTE_INLINE_RANGE */
9234
9235    /*
9236     * Extract args, call function.
9237     *  r0 = #of args (0-4)
9238     *  r10 = call index
9239     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9240     */
9241.LOP_EXECUTE_INLINE_RANGE_continue:
9242    rsb     r0, r0, #4                  @ r0<- 4-r0
9243    FETCH(r9, 2)                        @ r9<- CCCC
9244    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9245    bl      common_abort                @ (skipped due to ARM prefetch)
92464:  add     ip, r9, #3                  @ base+3
9247    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92483:  add     ip, r9, #2                  @ base+2
9249    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92502:  add     ip, r9, #1                  @ base+1
9251    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92521:  add     ip, r9, #0                  @ (nop)
9253    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92540:
9255    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9256    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9257    @ (not reached)
9258
9259.LOP_EXECUTE_INLINE_RANGE_table:
9260    .word   gDvmInlineOpsTable
9261
9262/* continuation for OP_IPUT_OBJECT_VOLATILE */
9263
9264    /*
9265     * Currently:
9266     *  r0 holds resolved field
9267     *  r9 holds object
9268     */
9269.LOP_IPUT_OBJECT_VOLATILE_finish:
9270    @bl      common_squeak0
9271    mov     r1, rINST, lsr #8           @ r1<- A+
9272    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9273    and     r1, r1, #15                 @ r1<- A
9274    cmp     r9, #0                      @ check object for null
9275    GET_VREG(r0, r1)                    @ r0<- fp[A]
9276    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9277    beq     common_errNullObject        @ object was null
9278    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9279    add     r9, r3                      @ r9<- direct ptr to target location
9280    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9281    SMP_DMB                            @ releasing store
9282    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
9283    cmp     r0, #0                      @ stored a null reference?
9284    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9285    GOTO_OPCODE(ip)                     @ jump to next instruction
9286
9287/* continuation for OP_SGET_OBJECT_VOLATILE */
9288
9289    /*
9290     * Continuation if the field has not yet been resolved.
9291     *  r1: BBBB field ref
9292     */
9293.LOP_SGET_OBJECT_VOLATILE_resolve:
9294    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9295    EXPORT_PC()                         @ resolve() could throw, so export now
9296    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9297    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9298    cmp     r0, #0                      @ success?
9299    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9300    b       common_exceptionThrown      @ no, handle exception
9301
9302/* continuation for OP_SPUT_OBJECT_VOLATILE */
9303.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9304    mov     r2, rINST, lsr #8           @ r2<- AA
9305    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9306    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9307    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9309    add     r0, #offStaticField_value   @ r0<- pointer to store target
9310    SMP_DMB                            @ releasing store
9311    str     r1, [r0]                    @ field<- vAA
9312    cmp     r1, #0                      @ stored a null object?
9313    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
9314    GOTO_OPCODE(ip)                     @ jump to next instruction
9315
9316    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9317    .global dvmAsmSisterEnd
9318dvmAsmSisterEnd:
9319
9320/* File: armv5te/footer.S */
9321
9322/*
9323 * ===========================================================================
9324 *  Common subroutines and data
9325 * ===========================================================================
9326 */
9327
9328
9329
9330    .text
9331    .align  2
9332
9333#if defined(WITH_JIT)
9334#if defined(WITH_SELF_VERIFICATION)
9335    .global dvmJitToInterpPunt
9336dvmJitToInterpPunt:
9337    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9338    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9339    mov    r3, #0
9340    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9341    b      jitSVShadowRunEnd            @ doesn't return
9342
9343    .global dvmJitToInterpSingleStep
9344dvmJitToInterpSingleStep:
9345    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9346    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9347    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9348    b      jitSVShadowRunEnd            @ doesn't return
9349
9350    .global dvmJitToInterpNoChainNoProfile
9351dvmJitToInterpNoChainNoProfile:
9352    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9353    mov    r0,rPC                       @ pass our target PC
9354    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9355    mov    r3, #0                       @ 0 means !inJitCodeCache
9356    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9357    b      jitSVShadowRunEnd            @ doesn't return
9358
9359    .global dvmJitToInterpTraceSelectNoChain
9360dvmJitToInterpTraceSelectNoChain:
9361    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9362    mov    r0,rPC                       @ pass our target PC
9363    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9364    mov    r3, #0                       @ 0 means !inJitCodeCache
9365    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9366    b      jitSVShadowRunEnd            @ doesn't return
9367
9368    .global dvmJitToInterpTraceSelect
9369dvmJitToInterpTraceSelect:
9370    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9371    ldr    r0,[lr, #-1]                 @ pass our target PC
9372    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9373    mov    r3, #0                       @ 0 means !inJitCodeCache
9374    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9375    b      jitSVShadowRunEnd            @ doesn't return
9376
9377    .global dvmJitToInterpBackwardBranch
9378dvmJitToInterpBackwardBranch:
9379    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9380    ldr    r0,[lr, #-1]                 @ pass our target PC
9381    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9382    mov    r3, #0                       @ 0 means !inJitCodeCache
9383    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9384    b      jitSVShadowRunEnd            @ doesn't return
9385
9386    .global dvmJitToInterpNormal
9387dvmJitToInterpNormal:
9388    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9389    ldr    r0,[lr, #-1]                 @ pass our target PC
9390    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9391    mov    r3, #0                       @ 0 means !inJitCodeCache
9392    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9393    b      jitSVShadowRunEnd            @ doesn't return
9394
9395    .global dvmJitToInterpNoChain
9396dvmJitToInterpNoChain:
9397    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9398    mov    r0,rPC                       @ pass our target PC
9399    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9400    mov    r3, #0                       @ 0 means !inJitCodeCache
9401    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9402    b      jitSVShadowRunEnd            @ doesn't return
9403#else
9404/*
9405 * Return from the translation cache to the interpreter when the compiler is
9406 * having issues translating/executing a Dalvik instruction. We have to skip
9407 * the code cache lookup otherwise it is possible to indefinitely bouce
9408 * between the interpreter and the code cache if the instruction that fails
9409 * to be compiled happens to be at a trace start.
9410 */
9411    .global dvmJitToInterpPunt
9412dvmJitToInterpPunt:
9413    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9414    mov    rPC, r0
9415#if defined(WITH_JIT_TUNING)
9416    mov    r0,lr
9417    bl     dvmBumpPunt;
9418#endif
9419    EXPORT_PC()
9420    mov    r0, #0
9421    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9422    adrl   rIBASE, dvmAsmInstructionStart
9423    FETCH_INST()
9424    GET_INST_OPCODE(ip)
9425    GOTO_OPCODE(ip)
9426
9427/*
9428 * Return to the interpreter to handle a single instruction.
9429 * On entry:
9430 *    r0 <= PC
9431 *    r1 <= PC of resume instruction
9432 *    lr <= resume point in translation
9433 */
9434    .global dvmJitToInterpSingleStep
9435dvmJitToInterpSingleStep:
9436    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9437    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9438    mov    r1,#kInterpEntryInstr
9439    @ enum is 4 byte in aapcs-EABI
9440    str    r1, [rGLUE, #offGlue_entryPoint]
9441    mov    rPC,r0
9442    EXPORT_PC()
9443
9444    adrl   rIBASE, dvmAsmInstructionStart
9445    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9446    str    r2,[rGLUE,#offGlue_jitState]
9447    mov    r1,#1                  @ set changeInterp to bail to debug interp
9448    b      common_gotoBail
9449
9450/*
9451 * Return from the translation cache and immediately request
9452 * a translation for the exit target.  Commonly used for callees.
9453 */
9454    .global dvmJitToInterpTraceSelectNoChain
9455dvmJitToInterpTraceSelectNoChain:
9456#if defined(WITH_JIT_TUNING)
9457    bl     dvmBumpNoChain
9458#endif
9459    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9460    mov    r0,rPC
9461    bl     dvmJitGetCodeAddr        @ Is there a translation?
9462    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9463    mov    r1, rPC                  @ arg1 of translation may need this
9464    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9465    cmp    r0,#0                    @ !0 means translation exists
9466    bxne   r0                       @ continue native execution if so
9467    b      2f                       @ branch over to use the interpreter
9468
9469/*
9470 * Return from the translation cache and immediately request
9471 * a translation for the exit target.  Commonly used following
9472 * invokes.
9473 */
9474    .global dvmJitToInterpTraceSelect
9475dvmJitToInterpTraceSelect:
9476    ldr    rPC,[lr, #-1]           @ get our target PC
9477    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9478    add    rINST,lr,#-5            @ save start of chain branch
9479    add    rINST, #-4              @  .. which is 9 bytes back
9480    mov    r0,rPC
9481    bl     dvmJitGetCodeAddr       @ Is there a translation?
9482    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9483    cmp    r0,#0
9484    beq    2f
9485    mov    r1,rINST
9486    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9487    mov    r1, rPC                  @ arg1 of translation may need this
9488    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9489    cmp    r0,#0                    @ successful chain?
9490    bxne   r0                       @ continue native execution
9491    b      toInterpreter            @ didn't chain - resume with interpreter
9492
9493/* No translation, so request one if profiling isn't disabled*/
94942:
9495    adrl   rIBASE, dvmAsmInstructionStart
9496    GET_JIT_PROF_TABLE(r0)
9497    FETCH_INST()
9498    cmp    r0, #0
9499    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9500    bne    common_selectTrace
9501    GET_INST_OPCODE(ip)
9502    GOTO_OPCODE(ip)
9503
9504/*
9505 * Return from the translation cache to the interpreter.
9506 * The return was done with a BLX from thumb mode, and
9507 * the following 32-bit word contains the target rPC value.
9508 * Note that lr (r14) will have its low-order bit set to denote
9509 * its thumb-mode origin.
9510 *
9511 * We'll need to stash our lr origin away, recover the new
9512 * target and then check to see if there is a translation available
9513 * for our new target.  If so, we do a translation chain and
9514 * go back to native execution.  Otherwise, it's back to the
9515 * interpreter (after treating this entry as a potential
9516 * trace start).
9517 */
9518    .global dvmJitToInterpNormal
9519dvmJitToInterpNormal:
9520    ldr    rPC,[lr, #-1]           @ get our target PC
9521    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9522    add    rINST,lr,#-5            @ save start of chain branch
9523    add    rINST,#-4               @ .. which is 9 bytes back
9524#if defined(WITH_JIT_TUNING)
9525    bl     dvmBumpNormal
9526#endif
9527    mov    r0,rPC
9528    bl     dvmJitGetCodeAddr        @ Is there a translation?
9529    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9530    cmp    r0,#0
9531    beq    toInterpreter            @ go if not, otherwise do chain
9532    mov    r1,rINST
9533    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9534    mov    r1, rPC                  @ arg1 of translation may need this
9535    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9536    cmp    r0,#0                    @ successful chain?
9537    bxne   r0                       @ continue native execution
9538    b      toInterpreter            @ didn't chain - resume with interpreter
9539
9540/*
9541 * Return from the translation cache to the interpreter to do method invocation.
9542 * Check if translation exists for the callee, but don't chain to it.
9543 */
9544    .global dvmJitToInterpNoChainNoProfile
9545dvmJitToInterpNoChainNoProfile:
9546#if defined(WITH_JIT_TUNING)
9547    bl     dvmBumpNoChain
9548#endif
9549    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9550    mov    r0,rPC
9551    bl     dvmJitGetCodeAddr        @ Is there a translation?
9552    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9553    mov    r1, rPC                  @ arg1 of translation may need this
9554    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9555    cmp    r0,#0
9556    bxne   r0                       @ continue native execution if so
9557    EXPORT_PC()
9558    adrl   rIBASE, dvmAsmInstructionStart
9559    FETCH_INST()
9560    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9561    GOTO_OPCODE(ip)                     @ jump to next instruction
9562
9563/*
9564 * Return from the translation cache to the interpreter to do method invocation.
9565 * Check if translation exists for the callee, but don't chain to it.
9566 */
9567    .global dvmJitToInterpNoChain
9568dvmJitToInterpNoChain:
9569#if defined(WITH_JIT_TUNING)
9570    bl     dvmBumpNoChain
9571#endif
9572    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9573    mov    r0,rPC
9574    bl     dvmJitGetCodeAddr        @ Is there a translation?
9575    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9576    mov    r1, rPC                  @ arg1 of translation may need this
9577    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9578    cmp    r0,#0
9579    bxne   r0                       @ continue native execution if so
9580#endif
9581
9582/*
9583 * No translation, restore interpreter regs and start interpreting.
9584 * rGLUE & rFP were preserved in the translated code, and rPC has
9585 * already been restored by the time we get here.  We'll need to set
9586 * up rIBASE & rINST, and load the address of the JitTable into r0.
9587 */
9588toInterpreter:
9589    EXPORT_PC()
9590    adrl   rIBASE, dvmAsmInstructionStart
9591    FETCH_INST()
9592    GET_JIT_PROF_TABLE(r0)
9593    @ NOTE: intended fallthrough
9594
9595/*
9596 * Common code to update potential trace start counter, and initiate
9597 * a trace-build if appropriate.  On entry, rPC should point to the
9598 * next instruction to execute, and rINST should be already loaded with
9599 * the next opcode word, and r0 holds a pointer to the jit profile
9600 * table (pJitProfTable).
9601 */
9602common_testUpdateProfile:
9603    cmp     r0,#0
9604    GET_INST_OPCODE(ip)
9605    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9606
9607common_updateProfile:
9608    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9609    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9610    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9611    GET_INST_OPCODE(ip)
9612    subs    r1,r1,#1           @ decrement counter
9613    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9614    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9615
9616/*
9617 * Here, we switch to the debug interpreter to request
9618 * trace selection.  First, though, check to see if there
9619 * is already a native translation in place (and, if so,
9620 * jump to it now).
9621 */
9622    GET_JIT_THRESHOLD(r1)
9623    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9624    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9625    EXPORT_PC()
9626    mov     r0,rPC
9627    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9628    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9629    mov     r1, rPC                     @ arg1 of translation may need this
9630    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9631    cmp     r0,#0
9632#if !defined(WITH_SELF_VERIFICATION)
9633    bxne    r0                          @ jump to the translation
9634    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9635    @ fall-through to common_selectTrace
9636#else
9637    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9638    beq     common_selectTrace
9639    /*
9640     * At this point, we have a target translation.  However, if
9641     * that translation is actually the interpret-only pseudo-translation
9642     * we want to treat it the same as no translation.
9643     */
9644    mov     r10, r0                     @ save target
9645    bl      dvmCompilerGetInterpretTemplate
9646    cmp     r0, r10                     @ special case?
9647    bne     jitSVShadowRunStart         @ set up self verification shadow space
9648    GET_INST_OPCODE(ip)
9649    GOTO_OPCODE(ip)
9650    /* no return */
9651#endif
9652
9653/*
9654 * On entry:
9655 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9656 */
9657common_selectTrace:
9658    str     r2,[rGLUE,#offGlue_jitState]
9659    mov     r2,#kInterpEntryInstr       @ normal entry reason
9660    str     r2,[rGLUE,#offGlue_entryPoint]
9661    mov     r1,#1                       @ set changeInterp
9662    b       common_gotoBail
9663
9664#if defined(WITH_SELF_VERIFICATION)
9665/*
9666 * Save PC and registers to shadow memory for self verification mode
9667 * before jumping to native translation.
9668 * On entry:
9669 *    rPC, rFP, rGLUE: the values that they should contain
9670 *    r10: the address of the target translation.
9671 */
9672jitSVShadowRunStart:
9673    mov     r0,rPC                      @ r0<- program counter
9674    mov     r1,rFP                      @ r1<- frame pointer
9675    mov     r2,rGLUE                    @ r2<- InterpState pointer
9676    mov     r3,r10                      @ r3<- target translation
9677    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9678    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9679    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9680    bx      r10                         @ jump to the translation
9681
9682/*
9683 * Restore PC, registers, and interpState to original values
9684 * before jumping back to the interpreter.
9685 */
9686jitSVShadowRunEnd:
9687    mov    r1,rFP                        @ pass ending fp
9688    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9689    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9690    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9691    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9692    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9693    cmp    r1,#0                         @ check for punt condition
9694    beq    1f
9695    mov    r2,#kJitSelfVerification      @ ask for self verification
9696    str    r2,[rGLUE,#offGlue_jitState]
9697    mov    r2,#kInterpEntryInstr         @ normal entry reason
9698    str    r2,[rGLUE,#offGlue_entryPoint]
9699    mov    r1,#1                         @ set changeInterp
9700    b      common_gotoBail
9701
97021:                                       @ exit to interpreter without check
9703    EXPORT_PC()
9704    adrl   rIBASE, dvmAsmInstructionStart
9705    FETCH_INST()
9706    GET_INST_OPCODE(ip)
9707    GOTO_OPCODE(ip)
9708#endif
9709
9710#endif
9711
9712/*
9713 * Common code when a backward branch is taken.
9714 *
9715 * TODO: we could avoid a branch by just setting r0 and falling through
9716 * into the common_periodicChecks code, and having a test on r0 at the
9717 * end determine if we should return to the caller or update & branch to
9718 * the next instr.
9719 *
9720 * On entry:
9721 *  r9 is PC adjustment *in bytes*
9722 */
9723common_backwardBranch:
9724    mov     r0, #kInterpEntryInstr
9725    bl      common_periodicChecks
9726#if defined(WITH_JIT)
9727    GET_JIT_PROF_TABLE(r0)
9728    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9729    cmp     r0,#0
9730    bne     common_updateProfile
9731    GET_INST_OPCODE(ip)
9732    GOTO_OPCODE(ip)
9733#else
9734    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9735    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9736    GOTO_OPCODE(ip)                     @ jump to next instruction
9737#endif
9738
9739
9740/*
9741 * Need to see if the thread needs to be suspended or debugger/profiler
9742 * activity has begun.  If so, we suspend the thread or side-exit to
9743 * the debug interpreter as appropriate.
9744 *
9745 * The common case is no activity on any of these, so we want to figure
9746 * that out quickly.  If something is up, we can then sort out what.
9747 *
9748 * We want to be fast if the VM was built without debugger or profiler
9749 * support, but we also need to recognize that the system is usually
9750 * shipped with both of these enabled.
9751 *
9752 * TODO: reduce this so we're just checking a single location.
9753 *
9754 * On entry:
9755 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9756 *  r9 is trampoline PC adjustment *in bytes*
9757 */
9758common_periodicChecks:
9759    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9760
9761#if defined(WITH_DEBUGGER)
9762    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9763#endif
9764#if defined(WITH_PROFILER)
9765    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9766#endif
9767
9768    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9769
9770#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9771    cmp     r1, #0                      @ debugger enabled?
9772    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9773    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9774    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9775    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9776#elif defined(WITH_DEBUGGER)
9777    cmp     r1, #0                      @ debugger enabled?
9778    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9779    orrsne  ip, ip, r1                  @ yes, ip<- suspend | debugger; set Z
9780    @ (if not enabled, Z was set by test for r1==0, which is what we want)
9781#elif defined (WITH_PROFILER)
9782    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9783    orrs    ip, ip, r2                  @ ip<- suspendCount | activeProfilers
9784#else
9785    cmp     ip, #0                      @ not ORing anything in; set Z
9786#endif
9787
9788    bxeq    lr                          @ all zero, return
9789
9790    /*
9791     * One or more interesting events have happened.  Figure out what.
9792     *
9793     * If debugging or profiling are compiled in, we need to disambiguate.
9794     *
9795     * r0 still holds the reentry type.
9796     */
9797#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9798    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9799    cmp     ip, #0                      @ want suspend?
9800    beq     1f                          @ no, must be debugger/profiler
9801#endif
9802
9803    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9804#if defined(WITH_JIT)
9805    /*
9806     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9807     * doubles as the Jit's on/off switch.
9808     */
9809    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9810    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9811    ldr     r3, [r3] @ r3 <- pJitProfTable
9812    EXPORT_PC()                         @ need for precise GC
9813    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9814#else
9815    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9816    EXPORT_PC()                         @ need for precise GC
9817#endif
9818    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9819    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9820
9821#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9822
9823    /*
9824     * Reload the debugger/profiler enable flags.  We're checking to see
9825     * if either of these got set while we were suspended.
9826     *
9827     * We can't really avoid the #ifdefs here, because the fields don't
9828     * exist when the feature is disabled.
9829     */
9830#if defined(WITH_DEBUGGER)
9831    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9832    cmp     r1, #0                      @ debugger enabled?
9833    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9834#else
9835    mov     r1, #0
9836#endif
9837#if defined(WITH_PROFILER)
9838    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9839    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9840#else
9841    mov     r2, #0
9842#endif
9843
9844    orrs    r1, r1, r2
9845    beq     2f
9846
98471:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9848    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9849    add     rPC, rPC, r9                @ update rPC
9850    mov     r1, #1                      @ "want switch" = true
9851    b       common_gotoBail             @ side exit
9852
9853#endif /*WITH_DEBUGGER || WITH_PROFILER*/
9854
98552:
9856    bx      lr                          @ nothing to do, return
9857
9858
9859/*
9860 * The equivalent of "goto bail", this calls through the "bail handler".
9861 *
9862 * State registers will be saved to the "glue" area before bailing.
9863 *
9864 * On entry:
9865 *  r1 is "bool changeInterp", indicating if we want to switch to the
9866 *     other interpreter or just bail all the way out
9867 */
9868common_gotoBail:
9869    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9870    mov     r0, rGLUE                   @ r0<- glue ptr
9871    b       dvmMterpStdBail             @ call(glue, changeInterp)
9872
9873    @add     r1, r1, #1                  @ using (boolean+1)
9874    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9875    @bl      _longjmp                    @ does not return
9876    @bl      common_abort
9877
9878
9879/*
9880 * Common code for method invocation with range.
9881 *
9882 * On entry:
9883 *  r0 is "Method* methodToCall", the method we're trying to call
9884 */
9885common_invokeMethodRange:
9886.LinvokeNewRange:
9887    @ prepare to copy args to "outs" area of current frame
9888    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9889    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9890    beq     .LinvokeArgsDone            @ if no args, skip the rest
9891    FETCH(r1, 2)                        @ r1<- CCCC
9892
9893    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9894    @ (very few methods have > 10 args; could unroll for common cases)
9895    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9896    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9897    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
98981:  ldr     r1, [r3], #4                @ val = *fp++
9899    subs    r2, r2, #1                  @ count--
9900    str     r1, [r10], #4               @ *outs++ = val
9901    bne     1b                          @ ...while count != 0
9902    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9903    b       .LinvokeArgsDone
9904
9905/*
9906 * Common code for method invocation without range.
9907 *
9908 * On entry:
9909 *  r0 is "Method* methodToCall", the method we're trying to call
9910 */
9911common_invokeMethodNoRange:
9912.LinvokeNewNoRange:
9913    @ prepare to copy args to "outs" area of current frame
9914    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9915    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9916    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9917    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9918    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9919    beq     .LinvokeArgsDone
9920
9921    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9922.LinvokeNonRange:
9923    rsb     r2, r2, #5                  @ r2<- 5-r2
9924    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9925    bl      common_abort                @ (skipped due to ARM prefetch)
99265:  and     ip, rINST, #0x0f00          @ isolate A
9927    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9928    mov     r0, r0                      @ nop
9929    str     r2, [r10, #-4]!             @ *--outs = vA
99304:  and     ip, r1, #0xf000             @ isolate G
9931    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9932    mov     r0, r0                      @ nop
9933    str     r2, [r10, #-4]!             @ *--outs = vG
99343:  and     ip, r1, #0x0f00             @ isolate F
9935    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9936    mov     r0, r0                      @ nop
9937    str     r2, [r10, #-4]!             @ *--outs = vF
99382:  and     ip, r1, #0x00f0             @ isolate E
9939    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9940    mov     r0, r0                      @ nop
9941    str     r2, [r10, #-4]!             @ *--outs = vE
99421:  and     ip, r1, #0x000f             @ isolate D
9943    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9944    mov     r0, r0                      @ nop
9945    str     r2, [r10, #-4]!             @ *--outs = vD
99460:  @ fall through to .LinvokeArgsDone
9947
9948.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9949    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9950    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9951    @ find space for the new stack frame, check for overflow
9952    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9953    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9954    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9955@    bl      common_dumpRegs
9956    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9957    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9958    cmp     r3, r9                      @ bottom < interpStackEnd?
9959    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9960    blo     .LstackOverflow             @ yes, this frame will overflow stack
9961
9962    @ set up newSaveArea
9963#ifdef EASY_GDB
9964    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9965    str     ip, [r10, #offStackSaveArea_prevSave]
9966#endif
9967    str     rFP, [r10, #offStackSaveArea_prevFrame]
9968    str     rPC, [r10, #offStackSaveArea_savedPc]
9969#if defined(WITH_JIT)
9970    mov     r9, #0
9971    str     r9, [r10, #offStackSaveArea_returnAddr]
9972#endif
9973    str     r0, [r10, #offStackSaveArea_method]
9974    tst     r3, #ACC_NATIVE
9975    bne     .LinvokeNative
9976
9977    /*
9978    stmfd   sp!, {r0-r3}
9979    bl      common_printNewline
9980    mov     r0, rFP
9981    mov     r1, #0
9982    bl      dvmDumpFp
9983    ldmfd   sp!, {r0-r3}
9984    stmfd   sp!, {r0-r3}
9985    mov     r0, r1
9986    mov     r1, r10
9987    bl      dvmDumpFp
9988    bl      common_printNewline
9989    ldmfd   sp!, {r0-r3}
9990    */
9991
9992    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9993    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9994    mov     rPC, r2                         @ publish new rPC
9995    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9996
9997    @ Update "glue" values for the new method
9998    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9999    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10000    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10001#if defined(WITH_JIT)
10002    GET_JIT_PROF_TABLE(r0)
10003    mov     rFP, r1                         @ fp = newFp
10004    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10005    mov     rINST, r9                       @ publish new rINST
10006    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10007    cmp     r0,#0
10008    bne     common_updateProfile
10009    GOTO_OPCODE(ip)                         @ jump to next instruction
10010#else
10011    mov     rFP, r1                         @ fp = newFp
10012    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10013    mov     rINST, r9                       @ publish new rINST
10014    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10015    GOTO_OPCODE(ip)                         @ jump to next instruction
10016#endif
10017
10018.LinvokeNative:
10019    @ Prep for the native call
10020    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10021    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10022    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10023    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10024    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10025    mov     r9, r3                      @ r9<- glue->self (preserve)
10026
10027    mov     r2, r0                      @ r2<- methodToCall
10028    mov     r0, r1                      @ r0<- newFp (points to args)
10029    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10030
10031#ifdef ASSIST_DEBUGGER
10032    /* insert fake function header to help gdb find the stack frame */
10033    b       .Lskip
10034    .type   dalvik_mterp, %function
10035dalvik_mterp:
10036    .fnstart
10037    MTERP_ENTRY1
10038    MTERP_ENTRY2
10039.Lskip:
10040#endif
10041
10042    @mov     lr, pc                      @ set return addr
10043    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10044    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10045
10046#if defined(WITH_JIT)
10047    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10048#endif
10049
10050    @ native return; r9=self, r10=newSaveArea
10051    @ equivalent to dvmPopJniLocals
10052    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10053    ldr     r1, [r9, #offThread_exception] @ check for exception
10054#if defined(WITH_JIT)
10055    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10056#endif
10057    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10058    cmp     r1, #0                      @ null?
10059    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10060#if defined(WITH_JIT)
10061    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10062#endif
10063    bne     common_exceptionThrown      @ no, handle exception
10064
10065    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10066    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10067    GOTO_OPCODE(ip)                     @ jump to next instruction
10068
10069.LstackOverflow:    @ r0=methodToCall
10070    mov     r1, r0                      @ r1<- methodToCall
10071    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10072    bl      dvmHandleStackOverflow
10073    b       common_exceptionThrown
10074#ifdef ASSIST_DEBUGGER
10075    .fnend
10076#endif
10077
10078
10079    /*
10080     * Common code for method invocation, calling through "glue code".
10081     *
10082     * TODO: now that we have range and non-range invoke handlers, this
10083     *       needs to be split into two.  Maybe just create entry points
10084     *       that set r9 and jump here?
10085     *
10086     * On entry:
10087     *  r0 is "Method* methodToCall", the method we're trying to call
10088     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10089     */
10090     .if    0
10091.LinvokeOld:
10092    sub     sp, sp, #8                  @ space for args + pad
10093    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10094    mov     r2, r0                      @ A2<- methodToCall
10095    mov     r0, rGLUE                   @ A0<- glue
10096    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10097    mov     r1, r9                      @ A1<- methodCallRange
10098    mov     r3, rINST, lsr #8           @ A3<- AA
10099    str     ip, [sp, #0]                @ A4<- ip
10100    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10101    add     sp, sp, #8                  @ remove arg area
10102    b       common_resumeAfterGlueCall  @ continue to next instruction
10103    .endif
10104
10105
10106
10107/*
10108 * Common code for handling a return instruction.
10109 *
10110 * This does not return.
10111 */
10112common_returnFromMethod:
10113.LreturnNew:
10114    mov     r0, #kInterpEntryReturn
10115    mov     r9, #0
10116    bl      common_periodicChecks
10117
10118    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10119    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10120    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10121    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10122                                        @ r2<- method we're returning to
10123    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10124    cmp     r2, #0                      @ is this a break frame?
10125    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10126    mov     r1, #0                      @ "want switch" = false
10127    beq     common_gotoBail             @ break frame, bail out completely
10128
10129    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10130    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10131    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10132    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10133#if defined(WITH_JIT)
10134    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10135    mov     rPC, r9                     @ publish new rPC
10136    str     r1, [rGLUE, #offGlue_methodClassDex]
10137    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10138    cmp     r10, #0                      @ caller is compiled code
10139    blxne   r10
10140    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10141    GOTO_OPCODE(ip)                     @ jump to next instruction
10142#else
10143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10144    mov     rPC, r9                     @ publish new rPC
10145    str     r1, [rGLUE, #offGlue_methodClassDex]
10146    GOTO_OPCODE(ip)                     @ jump to next instruction
10147#endif
10148
10149    /*
10150     * Return handling, calls through "glue code".
10151     */
10152     .if    0
10153.LreturnOld:
10154    SAVE_PC_FP_TO_GLUE()                @ export state
10155    mov     r0, rGLUE                   @ arg to function
10156    bl      dvmMterp_returnFromMethod
10157    b       common_resumeAfterGlueCall
10158    .endif
10159
10160
10161/*
10162 * Somebody has thrown an exception.  Handle it.
10163 *
10164 * If the exception processing code returns to us (instead of falling
10165 * out of the interpreter), continue with whatever the next instruction
10166 * now happens to be.
10167 *
10168 * This does not return.
10169 */
10170     .global dvmMterpCommonExceptionThrown
10171dvmMterpCommonExceptionThrown:
10172common_exceptionThrown:
10173.LexceptionNew:
10174    mov     r0, #kInterpEntryThrow
10175    mov     r9, #0
10176    bl      common_periodicChecks
10177
10178    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10179    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10180    mov     r1, r10                     @ r1<- self
10181    mov     r0, r9                      @ r0<- exception
10182    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10183    mov     r3, #0                      @ r3<- NULL
10184    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10185
10186    /* set up args and a local for "&fp" */
10187    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10188    str     rFP, [sp, #-4]!             @ *--sp = fp
10189    mov     ip, sp                      @ ip<- &fp
10190    mov     r3, #0                      @ r3<- false
10191    str     ip, [sp, #-4]!              @ *--sp = &fp
10192    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10193    mov     r0, r10                     @ r0<- self
10194    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10195    mov     r2, r9                      @ r2<- exception
10196    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10197    mov     r1, r1, asr #1              @ r1<- offset in code units
10198
10199    /* call, r0 gets catchRelPc (a code-unit offset) */
10200    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10201
10202    /* fix earlier stack overflow if necessary; may trash rFP */
10203    ldrb    r1, [r10, #offThread_stackOverflowed]
10204    cmp     r1, #0                      @ did we overflow earlier?
10205    beq     1f                          @ no, skip ahead
10206    mov     rFP, r0                     @ save relPc result in rFP
10207    mov     r0, r10                     @ r0<- self
10208    mov     r1, r9                      @ r1<- exception
10209    bl      dvmCleanupStackOverflow     @ call(self)
10210    mov     r0, rFP                     @ restore result
102111:
10212
10213    /* update frame pointer and check result from dvmFindCatchBlock */
10214    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10215    cmp     r0, #0                      @ is catchRelPc < 0?
10216    add     sp, sp, #8                  @ restore stack
10217    bmi     .LnotCaughtLocally
10218
10219    /* adjust locals to match self->curFrame and updated PC */
10220    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10221    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10222    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10223    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10224    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10225    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10226    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10227    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10228
10229    /* release the tracked alloc on the exception */
10230    mov     r0, r9                      @ r0<- exception
10231    mov     r1, r10                     @ r1<- self
10232    bl      dvmReleaseTrackedAlloc      @ release the exception
10233
10234    /* restore the exception if the handler wants it */
10235    FETCH_INST()                        @ load rINST from rPC
10236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10237    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10238    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10239    GOTO_OPCODE(ip)                     @ jump to next instruction
10240
10241.LnotCaughtLocally: @ r9=exception, r10=self
10242    /* fix stack overflow if necessary */
10243    ldrb    r1, [r10, #offThread_stackOverflowed]
10244    cmp     r1, #0                      @ did we overflow earlier?
10245    movne   r0, r10                     @ if yes: r0<- self
10246    movne   r1, r9                      @ if yes: r1<- exception
10247    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10248
10249    @ may want to show "not caught locally" debug messages here
10250#if DVM_SHOW_EXCEPTION >= 2
10251    /* call __android_log_print(prio, tag, format, ...) */
10252    /* "Exception %s from %s:%d not caught locally" */
10253    @ dvmLineNumFromPC(method, pc - method->insns)
10254    ldr     r0, [rGLUE, #offGlue_method]
10255    ldr     r1, [r0, #offMethod_insns]
10256    sub     r1, rPC, r1
10257    asr     r1, r1, #1
10258    bl      dvmLineNumFromPC
10259    str     r0, [sp, #-4]!
10260    @ dvmGetMethodSourceFile(method)
10261    ldr     r0, [rGLUE, #offGlue_method]
10262    bl      dvmGetMethodSourceFile
10263    str     r0, [sp, #-4]!
10264    @ exception->clazz->descriptor
10265    ldr     r3, [r9, #offObject_clazz]
10266    ldr     r3, [r3, #offClassObject_descriptor]
10267    @
10268    ldr     r2, strExceptionNotCaughtLocally
10269    ldr     r1, strLogTag
10270    mov     r0, #3                      @ LOG_DEBUG
10271    bl      __android_log_print
10272#endif
10273    str     r9, [r10, #offThread_exception] @ restore exception
10274    mov     r0, r9                      @ r0<- exception
10275    mov     r1, r10                     @ r1<- self
10276    bl      dvmReleaseTrackedAlloc      @ release the exception
10277    mov     r1, #0                      @ "want switch" = false
10278    b       common_gotoBail             @ bail out
10279
10280
10281    /*
10282     * Exception handling, calls through "glue code".
10283     */
10284    .if     0
10285.LexceptionOld:
10286    SAVE_PC_FP_TO_GLUE()                @ export state
10287    mov     r0, rGLUE                   @ arg to function
10288    bl      dvmMterp_exceptionThrown
10289    b       common_resumeAfterGlueCall
10290    .endif
10291
10292
10293/*
10294 * After returning from a "glued" function, pull out the updated
10295 * values and start executing at the next instruction.
10296 */
10297common_resumeAfterGlueCall:
10298    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10299    FETCH_INST()                        @ load rINST from rPC
10300    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10301    GOTO_OPCODE(ip)                     @ jump to next instruction
10302
10303/*
10304 * Invalid array index.
10305 */
10306common_errArrayIndex:
10307    EXPORT_PC()
10308    ldr     r0, strArrayIndexException
10309    mov     r1, #0
10310    bl      dvmThrowException
10311    b       common_exceptionThrown
10312
10313/*
10314 * Invalid array value.
10315 */
10316common_errArrayStore:
10317    EXPORT_PC()
10318    ldr     r0, strArrayStoreException
10319    mov     r1, #0
10320    bl      dvmThrowException
10321    b       common_exceptionThrown
10322
10323/*
10324 * Integer divide or mod by zero.
10325 */
10326common_errDivideByZero:
10327    EXPORT_PC()
10328    ldr     r0, strArithmeticException
10329    ldr     r1, strDivideByZero
10330    bl      dvmThrowException
10331    b       common_exceptionThrown
10332
10333/*
10334 * Attempt to allocate an array with a negative size.
10335 */
10336common_errNegativeArraySize:
10337    EXPORT_PC()
10338    ldr     r0, strNegativeArraySizeException
10339    mov     r1, #0
10340    bl      dvmThrowException
10341    b       common_exceptionThrown
10342
10343/*
10344 * Invocation of a non-existent method.
10345 */
10346common_errNoSuchMethod:
10347    EXPORT_PC()
10348    ldr     r0, strNoSuchMethodError
10349    mov     r1, #0
10350    bl      dvmThrowException
10351    b       common_exceptionThrown
10352
10353/*
10354 * We encountered a null object when we weren't expecting one.  We
10355 * export the PC, throw a NullPointerException, and goto the exception
10356 * processing code.
10357 */
10358common_errNullObject:
10359    EXPORT_PC()
10360    ldr     r0, strNullPointerException
10361    mov     r1, #0
10362    bl      dvmThrowException
10363    b       common_exceptionThrown
10364
10365/*
10366 * For debugging, cause an immediate fault.  The source address will
10367 * be in lr (use a bl instruction to jump here).
10368 */
10369common_abort:
10370    ldr     pc, .LdeadFood
10371.LdeadFood:
10372    .word   0xdeadf00d
10373
10374/*
10375 * Spit out a "we were here", preserving all registers.  (The attempt
10376 * to save ip won't work, but we need to save an even number of
10377 * registers for EABI 64-bit stack alignment.)
10378 */
10379    .macro  SQUEAK num
10380common_squeak\num:
10381    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10382    ldr     r0, strSqueak
10383    mov     r1, #\num
10384    bl      printf
10385    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10386    bx      lr
10387    .endm
10388
10389    SQUEAK  0
10390    SQUEAK  1
10391    SQUEAK  2
10392    SQUEAK  3
10393    SQUEAK  4
10394    SQUEAK  5
10395
10396/*
10397 * Spit out the number in r0, preserving registers.
10398 */
10399common_printNum:
10400    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10401    mov     r1, r0
10402    ldr     r0, strSqueak
10403    bl      printf
10404    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10405    bx      lr
10406
10407/*
10408 * Print a newline, preserving registers.
10409 */
10410common_printNewline:
10411    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10412    ldr     r0, strNewline
10413    bl      printf
10414    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10415    bx      lr
10416
10417    /*
10418     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10419     */
10420common_printHex:
10421    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10422    mov     r1, r0
10423    ldr     r0, strPrintHex
10424    bl      printf
10425    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10426    bx      lr
10427
10428/*
10429 * Print the 64-bit quantity in r0-r1, preserving registers.
10430 */
10431common_printLong:
10432    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10433    mov     r3, r1
10434    mov     r2, r0
10435    ldr     r0, strPrintLong
10436    bl      printf
10437    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10438    bx      lr
10439
10440/*
10441 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10442 */
10443common_printMethod:
10444    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10445    bl      dvmMterpPrintMethod
10446    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10447    bx      lr
10448
10449/*
10450 * Call a C helper function that dumps regs and possibly some
10451 * additional info.  Requires the C function to be compiled in.
10452 */
10453    .if     0
10454common_dumpRegs:
10455    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10456    bl      dvmMterpDumpArmRegs
10457    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10458    bx      lr
10459    .endif
10460
10461#if 0
10462/*
10463 * Experiment on VFP mode.
10464 *
10465 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10466 *
10467 * Updates the bits specified by "mask", setting them to the values in "val".
10468 */
10469setFPSCR:
10470    and     r0, r0, r1                  @ make sure no stray bits are set
10471    fmrx    r2, fpscr                   @ get VFP reg
10472    mvn     r1, r1                      @ bit-invert mask
10473    and     r2, r2, r1                  @ clear masked bits
10474    orr     r2, r2, r0                  @ set specified bits
10475    fmxr    fpscr, r2                   @ set VFP reg
10476    mov     r0, r2                      @ return new value
10477    bx      lr
10478
10479    .align  2
10480    .global dvmConfigureFP
10481    .type   dvmConfigureFP, %function
10482dvmConfigureFP:
10483    stmfd   sp!, {ip, lr}
10484    /* 0x03000000 sets DN/FZ */
10485    /* 0x00009f00 clears the six exception enable flags */
10486    bl      common_squeak0
10487    mov     r0, #0x03000000             @ r0<- 0x03000000
10488    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10489    bl      setFPSCR
10490    ldmfd   sp!, {ip, pc}
10491#endif
10492
10493
10494/*
10495 * String references, must be close to the code that uses them.
10496 */
10497    .align  2
10498strArithmeticException:
10499    .word   .LstrArithmeticException
10500strArrayIndexException:
10501    .word   .LstrArrayIndexException
10502strArrayStoreException:
10503    .word   .LstrArrayStoreException
10504strDivideByZero:
10505    .word   .LstrDivideByZero
10506strNegativeArraySizeException:
10507    .word   .LstrNegativeArraySizeException
10508strNoSuchMethodError:
10509    .word   .LstrNoSuchMethodError
10510strNullPointerException:
10511    .word   .LstrNullPointerException
10512
10513strLogTag:
10514    .word   .LstrLogTag
10515strExceptionNotCaughtLocally:
10516    .word   .LstrExceptionNotCaughtLocally
10517
10518strNewline:
10519    .word   .LstrNewline
10520strSqueak:
10521    .word   .LstrSqueak
10522strPrintHex:
10523    .word   .LstrPrintHex
10524strPrintLong:
10525    .word   .LstrPrintLong
10526
10527/*
10528 * Zero-terminated ASCII string data.
10529 *
10530 * On ARM we have two choices: do like gcc does, and LDR from a .word
10531 * with the address, or use an ADR pseudo-op to get the address
10532 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10533 * PC-relative addressing mode and hence has a limited range, which
10534 * makes it not work well with mergeable string sections.
10535 */
10536    .section .rodata.str1.4,"aMS",%progbits,1
10537
10538.LstrBadEntryPoint:
10539    .asciz  "Bad entry point %d\n"
10540.LstrArithmeticException:
10541    .asciz  "Ljava/lang/ArithmeticException;"
10542.LstrArrayIndexException:
10543    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10544.LstrArrayStoreException:
10545    .asciz  "Ljava/lang/ArrayStoreException;"
10546.LstrClassCastException:
10547    .asciz  "Ljava/lang/ClassCastException;"
10548.LstrDivideByZero:
10549    .asciz  "divide by zero"
10550.LstrFilledNewArrayNotImpl:
10551    .asciz  "filled-new-array only implemented for objects and 'int'"
10552.LstrInternalError:
10553    .asciz  "Ljava/lang/InternalError;"
10554.LstrInstantiationError:
10555    .asciz  "Ljava/lang/InstantiationError;"
10556.LstrNegativeArraySizeException:
10557    .asciz  "Ljava/lang/NegativeArraySizeException;"
10558.LstrNoSuchMethodError:
10559    .asciz  "Ljava/lang/NoSuchMethodError;"
10560.LstrNullPointerException:
10561    .asciz  "Ljava/lang/NullPointerException;"
10562
10563.LstrLogTag:
10564    .asciz  "mterp"
10565.LstrExceptionNotCaughtLocally:
10566    .asciz  "Exception %s from %s:%d not caught locally\n"
10567
10568.LstrNewline:
10569    .asciz  "\n"
10570.LstrSqueak:
10571    .asciz  "<%d>"
10572.LstrPrintHex:
10573    .asciz  "<0x%x>"
10574.LstrPrintLong:
10575    .asciz  "<%lld>"
10576
10577