InterpAsm-armv7-a.S revision c95e0fbce4f77b2b08eb48205e405793de0d4248
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 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
189#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204#if defined(WITH_JIT)
205#include "../common/jit-config.h"
206#endif
207
208/* File: armv5te/platform.S */
209/*
210 * ===========================================================================
211 *  CPU-version-specific defines
212 * ===========================================================================
213 */
214
215/*
216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
217 * one-way branch.
218 *
219 * May modify IP.  Does not modify LR.
220 */
221.macro  LDR_PC source
222    ldr     pc, \source
223.endm
224
225/*
226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
227 * Jump to subroutine.
228 *
229 * May modify IP and LR.
230 */
231.macro  LDR_PC_LR source
232    mov     lr, pc
233    ldr     pc, \source
234.endm
235
236/*
237 * Macro for "LDMFD SP!, {...regs...,PC}".
238 *
239 * May modify IP and LR.
240 */
241.macro  LDMFD_PC regs
242    ldmfd   sp!, {\regs,pc}
243.endm
244
245
246/* File: armv5te/entry.S */
247/*
248 * Copyright (C) 2008 The Android Open Source Project
249 *
250 * Licensed under the Apache License, Version 2.0 (the "License");
251 * you may not use this file except in compliance with the License.
252 * You may obtain a copy of the License at
253 *
254 *      http://www.apache.org/licenses/LICENSE-2.0
255 *
256 * Unless required by applicable law or agreed to in writing, software
257 * distributed under the License is distributed on an "AS IS" BASIS,
258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259 * See the License for the specific language governing permissions and
260 * limitations under the License.
261 */
262/*
263 * Interpreter entry point.
264 */
265
266/*
267 * We don't have formal stack frames, so gdb scans upward in the code
268 * to find the start of the function (a label with the %function type),
269 * and then looks at the next few instructions to figure out what
270 * got pushed onto the stack.  From this it figures out how to restore
271 * the registers, including PC, for the previous stack frame.  If gdb
272 * sees a non-function label, it stops scanning, so either we need to
273 * have nothing but assembler-local labels between the entry point and
274 * the break, or we need to fake it out.
275 *
276 * When this is defined, we add some stuff to make gdb less confused.
277 */
278#define ASSIST_DEBUGGER 1
279
280    .text
281    .align  2
282    .global dvmMterpStdRun
283    .type   dvmMterpStdRun, %function
284
285/*
286 * On entry:
287 *  r0  MterpGlue* glue
288 *
289 * This function returns a boolean "changeInterp" value.  The return comes
290 * via a call to dvmMterpStdBail().
291 */
292dvmMterpStdRun:
293#define MTERP_ENTRY1 \
294    .save {r4-r10,fp,lr}; \
295    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
296#define MTERP_ENTRY2 \
297    .pad    #4; \
298    sub     sp, sp, #4                  @ align 64
299
300    .fnstart
301    MTERP_ENTRY1
302    MTERP_ENTRY2
303
304    /* save stack pointer, add magic word for debuggerd */
305    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
306
307    /* set up "named" registers, figure out entry point */
308    mov     rGLUE, r0                   @ set rGLUE
309    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
310    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
311    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
312    cmp     r1, #kInterpEntryInstr      @ usual case?
313    bne     .Lnot_instr                 @ no, handle it
314
315#if defined(WITH_JIT)
316.LentryInstr:
317    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
318    /* Entry is always a possible trace start */
319    GET_JIT_PROF_TABLE(r0)
320    FETCH_INST()
321    mov    r1, #0                       @ prepare the value for the new state
322    str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
323    cmp    r0,#0
324    bne    common_updateProfile
325    GET_INST_OPCODE(ip)
326    GOTO_OPCODE(ip)
327#else
328    /* start executing the instruction at rPC */
329    FETCH_INST()                        @ load rINST from rPC
330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
331    GOTO_OPCODE(ip)                     @ jump to next instruction
332#endif
333
334.Lnot_instr:
335    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
336    beq     common_returnFromMethod
337
338.Lnot_return:
339    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
340    beq     common_exceptionThrown
341
342#if defined(WITH_JIT)
343.Lnot_throw:
344    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
345    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
346    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
347    bne     .Lbad_arg
348    cmp     rPC,r2
349    bne     .LentryInstr                @ must have branched, don't resume
350#if defined(WITH_SELF_VERIFICATION)
351    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
352    b       jitSVShadowRunStart         @ re-enter the translation after the
353                                        @ single-stepped instruction
354    @noreturn
355#endif
356    mov     r1, #kInterpEntryInstr
357    str     r1, [rGLUE, #offGlue_entryPoint]
358    bx      r10                         @ re-enter the translation
359#endif
360
361.Lbad_arg:
362    ldr     r0, strBadEntryPoint
363    @ r1 holds value of entryPoint
364    bl      printf
365    bl      dvmAbort
366    .fnend
367
368
369    .global dvmMterpStdBail
370    .type   dvmMterpStdBail, %function
371
372/*
373 * Restore the stack pointer and PC from the save point established on entry.
374 * This is essentially the same as a longjmp, but should be cheaper.  The
375 * last instruction causes us to return to whoever called dvmMterpStdRun.
376 *
377 * We pushed some registers on the stack in dvmMterpStdRun, then saved
378 * SP and LR.  Here we restore SP, restore the registers, and then restore
379 * LR to PC.
380 *
381 * On entry:
382 *  r0  MterpGlue* glue
383 *  r1  bool changeInterp
384 */
385dvmMterpStdBail:
386    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
387    mov     r0, r1                          @ return the changeInterp value
388    add     sp, sp, #4                      @ un-align 64
389    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
390
391
392/*
393 * String references.
394 */
395strBadEntryPoint:
396    .word   .LstrBadEntryPoint
397
398
399
400    .global dvmAsmInstructionStart
401    .type   dvmAsmInstructionStart, %function
402dvmAsmInstructionStart = .L_OP_NOP
403    .text
404
405/* ------------------------------ */
406    .balign 64
407.L_OP_NOP: /* 0x00 */
408/* File: armv5te/OP_NOP.S */
409    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
410    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
411    GOTO_OPCODE(ip)                     @ execute it
412
413#ifdef ASSIST_DEBUGGER
414    /* insert fake function header to help gdb find the stack frame */
415    .type   dalvik_inst, %function
416dalvik_inst:
417    .fnstart
418    MTERP_ENTRY1
419    MTERP_ENTRY2
420    .fnend
421#endif
422
423
424/* ------------------------------ */
425    .balign 64
426.L_OP_MOVE: /* 0x01 */
427/* File: armv6t2/OP_MOVE.S */
428    /* for move, move-object, long-to-int */
429    /* op vA, vB */
430    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
431    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
432    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
433    GET_VREG(r2, r1)                    @ r2<- fp[B]
434    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
435    SET_VREG(r2, r0)                    @ fp[A]<- r2
436    GOTO_OPCODE(ip)                     @ execute next instruction
437
438
439/* ------------------------------ */
440    .balign 64
441.L_OP_MOVE_FROM16: /* 0x02 */
442/* File: armv5te/OP_MOVE_FROM16.S */
443    /* for: move/from16, move-object/from16 */
444    /* op vAA, vBBBB */
445    FETCH(r1, 1)                        @ r1<- BBBB
446    mov     r0, rINST, lsr #8           @ r0<- AA
447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
448    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
449    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
450    SET_VREG(r2, r0)                    @ fp[AA]<- r2
451    GOTO_OPCODE(ip)                     @ jump to next instruction
452
453
454/* ------------------------------ */
455    .balign 64
456.L_OP_MOVE_16: /* 0x03 */
457/* File: armv5te/OP_MOVE_16.S */
458    /* for: move/16, move-object/16 */
459    /* op vAAAA, vBBBB */
460    FETCH(r1, 2)                        @ r1<- BBBB
461    FETCH(r0, 1)                        @ r0<- AAAA
462    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
463    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
464    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
465    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
466    GOTO_OPCODE(ip)                     @ jump to next instruction
467
468
469/* ------------------------------ */
470    .balign 64
471.L_OP_MOVE_WIDE: /* 0x04 */
472/* File: armv6t2/OP_MOVE_WIDE.S */
473    /* move-wide vA, vB */
474    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
475    mov     r3, rINST, lsr #12          @ r3<- B
476    ubfx    r2, rINST, #8, #4           @ r2<- A
477    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
478    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
479    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
480    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
482    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
483    GOTO_OPCODE(ip)                     @ jump to next instruction
484
485
486/* ------------------------------ */
487    .balign 64
488.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
489/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
490    /* move-wide/from16 vAA, vBBBB */
491    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
492    FETCH(r3, 1)                        @ r3<- BBBB
493    mov     r2, rINST, lsr #8           @ r2<- AA
494    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
495    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
496    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
497    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
498    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
499    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
500    GOTO_OPCODE(ip)                     @ jump to next instruction
501
502
503/* ------------------------------ */
504    .balign 64
505.L_OP_MOVE_WIDE_16: /* 0x06 */
506/* File: armv5te/OP_MOVE_WIDE_16.S */
507    /* move-wide/16 vAAAA, vBBBB */
508    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
509    FETCH(r3, 2)                        @ r3<- BBBB
510    FETCH(r2, 1)                        @ r2<- AAAA
511    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
512    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
513    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
514    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
515    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
516    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
517    GOTO_OPCODE(ip)                     @ jump to next instruction
518
519
520/* ------------------------------ */
521    .balign 64
522.L_OP_MOVE_OBJECT: /* 0x07 */
523/* File: armv5te/OP_MOVE_OBJECT.S */
524/* File: armv5te/OP_MOVE.S */
525    /* for move, move-object, long-to-int */
526    /* op vA, vB */
527    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
528    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
529    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
530    GET_VREG(r2, r1)                    @ r2<- fp[B]
531    and     r0, r0, #15
532    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
533    SET_VREG(r2, r0)                    @ fp[A]<- r2
534    GOTO_OPCODE(ip)                     @ execute next instruction
535
536
537
538/* ------------------------------ */
539    .balign 64
540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
542/* File: armv5te/OP_MOVE_FROM16.S */
543    /* for: move/from16, move-object/from16 */
544    /* op vAA, vBBBB */
545    FETCH(r1, 1)                        @ r1<- BBBB
546    mov     r0, rINST, lsr #8           @ r0<- AA
547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
548    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
550    SET_VREG(r2, r0)                    @ fp[AA]<- r2
551    GOTO_OPCODE(ip)                     @ jump to next instruction
552
553
554
555/* ------------------------------ */
556    .balign 64
557.L_OP_MOVE_OBJECT_16: /* 0x09 */
558/* File: armv5te/OP_MOVE_OBJECT_16.S */
559/* File: armv5te/OP_MOVE_16.S */
560    /* for: move/16, move-object/16 */
561    /* op vAAAA, vBBBB */
562    FETCH(r1, 2)                        @ r1<- BBBB
563    FETCH(r0, 1)                        @ r0<- AAAA
564    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
565    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
566    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
567    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
568    GOTO_OPCODE(ip)                     @ jump to next instruction
569
570
571
572/* ------------------------------ */
573    .balign 64
574.L_OP_MOVE_RESULT: /* 0x0a */
575/* File: armv5te/OP_MOVE_RESULT.S */
576    /* for: move-result, move-result-object */
577    /* op vAA */
578    mov     r2, rINST, lsr #8           @ r2<- AA
579    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
580    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
582    SET_VREG(r0, r2)                    @ fp[AA]<- r0
583    GOTO_OPCODE(ip)                     @ jump to next instruction
584
585
586/* ------------------------------ */
587    .balign 64
588.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
589/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
590    /* move-result-wide vAA */
591    mov     r2, rINST, lsr #8           @ r2<- AA
592    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
593    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
594    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
595    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
596    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
597    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
598    GOTO_OPCODE(ip)                     @ jump to next instruction
599
600
601/* ------------------------------ */
602    .balign 64
603.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
604/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
605/* File: armv5te/OP_MOVE_RESULT.S */
606    /* for: move-result, move-result-object */
607    /* op vAA */
608    mov     r2, rINST, lsr #8           @ r2<- AA
609    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
610    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
611    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
612    SET_VREG(r0, r2)                    @ fp[AA]<- r0
613    GOTO_OPCODE(ip)                     @ jump to next instruction
614
615
616
617/* ------------------------------ */
618    .balign 64
619.L_OP_MOVE_EXCEPTION: /* 0x0d */
620/* File: armv5te/OP_MOVE_EXCEPTION.S */
621    /* move-exception vAA */
622    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
623    mov     r2, rINST, lsr #8           @ r2<- AA
624    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
625    mov     r1, #0                      @ r1<- 0
626    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
627    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
628    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
629    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
630    GOTO_OPCODE(ip)                     @ jump to next instruction
631
632
633/* ------------------------------ */
634    .balign 64
635.L_OP_RETURN_VOID: /* 0x0e */
636/* File: armv5te/OP_RETURN_VOID.S */
637    b       common_returnFromMethod
638
639
640/* ------------------------------ */
641    .balign 64
642.L_OP_RETURN: /* 0x0f */
643/* File: armv5te/OP_RETURN.S */
644    /*
645     * Return a 32-bit value.  Copies the return value into the "glue"
646     * structure, then jumps to the return handler.
647     *
648     * for: return, return-object
649     */
650    /* op vAA */
651    mov     r2, rINST, lsr #8           @ r2<- AA
652    GET_VREG(r0, r2)                    @ r0<- vAA
653    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
654    b       common_returnFromMethod
655
656
657/* ------------------------------ */
658    .balign 64
659.L_OP_RETURN_WIDE: /* 0x10 */
660/* File: armv5te/OP_RETURN_WIDE.S */
661    /*
662     * Return a 64-bit value.  Copies the return value into the "glue"
663     * structure, then jumps to the return handler.
664     */
665    /* return-wide vAA */
666    mov     r2, rINST, lsr #8           @ r2<- AA
667    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
668    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
669    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
670    stmia   r3, {r0-r1}                 @ retval<- r0/r1
671    b       common_returnFromMethod
672
673
674/* ------------------------------ */
675    .balign 64
676.L_OP_RETURN_OBJECT: /* 0x11 */
677/* File: armv5te/OP_RETURN_OBJECT.S */
678/* File: armv5te/OP_RETURN.S */
679    /*
680     * Return a 32-bit value.  Copies the return value into the "glue"
681     * structure, then jumps to the return handler.
682     *
683     * for: return, return-object
684     */
685    /* op vAA */
686    mov     r2, rINST, lsr #8           @ r2<- AA
687    GET_VREG(r0, r2)                    @ r0<- vAA
688    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
689    b       common_returnFromMethod
690
691
692
693/* ------------------------------ */
694    .balign 64
695.L_OP_CONST_4: /* 0x12 */
696/* File: armv6t2/OP_CONST_4.S */
697    /* const/4 vA, #+B */
698    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
699    ubfx    r0, rINST, #8, #4           @ r0<- A
700    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
701    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
702    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
703    SET_VREG(r1, r0)                    @ fp[A]<- r1
704    GOTO_OPCODE(ip)                     @ execute next instruction
705
706
707/* ------------------------------ */
708    .balign 64
709.L_OP_CONST_16: /* 0x13 */
710/* File: armv5te/OP_CONST_16.S */
711    /* const/16 vAA, #+BBBB */
712    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
713    mov     r3, rINST, lsr #8           @ r3<- AA
714    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
715    SET_VREG(r0, r3)                    @ vAA<- r0
716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
717    GOTO_OPCODE(ip)                     @ jump to next instruction
718
719
720/* ------------------------------ */
721    .balign 64
722.L_OP_CONST: /* 0x14 */
723/* File: armv5te/OP_CONST.S */
724    /* const vAA, #+BBBBbbbb */
725    mov     r3, rINST, lsr #8           @ r3<- AA
726    FETCH(r0, 1)                        @ r0<- bbbb (low)
727    FETCH(r1, 2)                        @ r1<- BBBB (high)
728    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
729    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
731    SET_VREG(r0, r3)                    @ vAA<- r0
732    GOTO_OPCODE(ip)                     @ jump to next instruction
733
734
735/* ------------------------------ */
736    .balign 64
737.L_OP_CONST_HIGH16: /* 0x15 */
738/* File: armv5te/OP_CONST_HIGH16.S */
739    /* const/high16 vAA, #+BBBB0000 */
740    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
741    mov     r3, rINST, lsr #8           @ r3<- AA
742    mov     r0, r0, lsl #16             @ r0<- BBBB0000
743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744    SET_VREG(r0, r3)                    @ vAA<- r0
745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746    GOTO_OPCODE(ip)                     @ jump to next instruction
747
748
749/* ------------------------------ */
750    .balign 64
751.L_OP_CONST_WIDE_16: /* 0x16 */
752/* File: armv5te/OP_CONST_WIDE_16.S */
753    /* const-wide/16 vAA, #+BBBB */
754    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
755    mov     r3, rINST, lsr #8           @ r3<- AA
756    mov     r1, r0, asr #31             @ r1<- ssssssss
757    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
758    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
760    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
761    GOTO_OPCODE(ip)                     @ jump to next instruction
762
763
764/* ------------------------------ */
765    .balign 64
766.L_OP_CONST_WIDE_32: /* 0x17 */
767/* File: armv5te/OP_CONST_WIDE_32.S */
768    /* const-wide/32 vAA, #+BBBBbbbb */
769    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
770    mov     r3, rINST, lsr #8           @ r3<- AA
771    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
772    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
773    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
774    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
775    mov     r1, r0, asr #31             @ r1<- ssssssss
776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
777    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
778    GOTO_OPCODE(ip)                     @ jump to next instruction
779
780
781/* ------------------------------ */
782    .balign 64
783.L_OP_CONST_WIDE: /* 0x18 */
784/* File: armv5te/OP_CONST_WIDE.S */
785    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
786    FETCH(r0, 1)                        @ r0<- bbbb (low)
787    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
788    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
789    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
790    FETCH(r3, 4)                        @ r3<- HHHH (high)
791    mov     r9, rINST, lsr #8           @ r9<- AA
792    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
793    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
794    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
796    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
797    GOTO_OPCODE(ip)                     @ jump to next instruction
798
799
800/* ------------------------------ */
801    .balign 64
802.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
803/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
804    /* const-wide/high16 vAA, #+BBBB000000000000 */
805    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
806    mov     r3, rINST, lsr #8           @ r3<- AA
807    mov     r0, #0                      @ r0<- 00000000
808    mov     r1, r1, lsl #16             @ r1<- BBBB0000
809    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
810    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
812    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
813    GOTO_OPCODE(ip)                     @ jump to next instruction
814
815
816/* ------------------------------ */
817    .balign 64
818.L_OP_CONST_STRING: /* 0x1a */
819/* File: armv5te/OP_CONST_STRING.S */
820    /* const/string vAA, String@BBBB */
821    FETCH(r1, 1)                        @ r1<- BBBB
822    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
823    mov     r9, rINST, lsr #8           @ r9<- AA
824    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
825    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
826    cmp     r0, #0                      @ not yet resolved?
827    beq     .LOP_CONST_STRING_resolve
828    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
830    SET_VREG(r0, r9)                    @ vAA<- r0
831    GOTO_OPCODE(ip)                     @ jump to next instruction
832
833/* ------------------------------ */
834    .balign 64
835.L_OP_CONST_STRING_JUMBO: /* 0x1b */
836/* File: armv5te/OP_CONST_STRING_JUMBO.S */
837    /* const/string vAA, String@BBBBBBBB */
838    FETCH(r0, 1)                        @ r0<- bbbb (low)
839    FETCH(r1, 2)                        @ r1<- BBBB (high)
840    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
841    mov     r9, rINST, lsr #8           @ r9<- AA
842    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
843    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
844    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
845    cmp     r0, #0
846    beq     .LOP_CONST_STRING_JUMBO_resolve
847    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
849    SET_VREG(r0, r9)                    @ vAA<- r0
850    GOTO_OPCODE(ip)                     @ jump to next instruction
851
852/* ------------------------------ */
853    .balign 64
854.L_OP_CONST_CLASS: /* 0x1c */
855/* File: armv5te/OP_CONST_CLASS.S */
856    /* const/class vAA, Class@BBBB */
857    FETCH(r1, 1)                        @ r1<- BBBB
858    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
859    mov     r9, rINST, lsr #8           @ r9<- AA
860    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
861    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
862    cmp     r0, #0                      @ not yet resolved?
863    beq     .LOP_CONST_CLASS_resolve
864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
866    SET_VREG(r0, r9)                    @ vAA<- r0
867    GOTO_OPCODE(ip)                     @ jump to next instruction
868
869/* ------------------------------ */
870    .balign 64
871.L_OP_MONITOR_ENTER: /* 0x1d */
872/* File: armv5te/OP_MONITOR_ENTER.S */
873    /*
874     * Synchronize on an object.
875     */
876    /* monitor-enter vAA */
877    mov     r2, rINST, lsr #8           @ r2<- AA
878    GET_VREG(r1, r2)                    @ r1<- vAA (object)
879    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
880    cmp     r1, #0                      @ null object?
881    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
882    beq     common_errNullObject        @ null object, throw an exception
883    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
884    bl      dvmLockObject               @ call(self, obj)
885#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
886    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
887    ldr     r1, [r0, #offThread_exception] @ check for exception
888    cmp     r1, #0
889    bne     common_exceptionThrown      @ exception raised, bail out
890#endif
891    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
892    GOTO_OPCODE(ip)                     @ jump to next instruction
893
894
895/* ------------------------------ */
896    .balign 64
897.L_OP_MONITOR_EXIT: /* 0x1e */
898/* File: armv5te/OP_MONITOR_EXIT.S */
899    /*
900     * Unlock an object.
901     *
902     * Exceptions that occur when unlocking a monitor need to appear as
903     * if they happened at the following instruction.  See the Dalvik
904     * instruction spec.
905     */
906    /* monitor-exit vAA */
907    mov     r2, rINST, lsr #8           @ r2<- AA
908    EXPORT_PC()                         @ before fetch: export the PC
909    GET_VREG(r1, r2)                    @ r1<- vAA (object)
910    cmp     r1, #0                      @ null object?
911    beq     1f                          @ yes
912    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
913    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
914    cmp     r0, #0                      @ failed?
915    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
916    beq     common_exceptionThrown      @ yes, exception is pending
917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918    GOTO_OPCODE(ip)                     @ jump to next instruction
9191:
920    FETCH_ADVANCE_INST(1)               @ advance before throw
921    b      common_errNullObject
922
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/* ------------------------------ */
1000    .balign 64
1001.L_OP_NEW_INSTANCE: /* 0x22 */
1002/* File: armv5te/OP_NEW_INSTANCE.S */
1003    /*
1004     * Create a new instance of a class.
1005     */
1006    /* new-instance vAA, class@BBBB */
1007    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1008    FETCH(r1, 1)                        @ r1<- BBBB
1009    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1010    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1011    EXPORT_PC()                         @ req'd for init, resolve, alloc
1012    cmp     r0, #0                      @ already resolved?
1013    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1014.LOP_NEW_INSTANCE_resolved:   @ r0=class
1015    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1016    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1017    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1018.LOP_NEW_INSTANCE_initialized: @ r0=class
1019    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1020    bl      dvmAllocObject              @ r0<- new object
1021    b       .LOP_NEW_INSTANCE_finish          @ continue
1022
1023/* ------------------------------ */
1024    .balign 64
1025.L_OP_NEW_ARRAY: /* 0x23 */
1026/* File: armv5te/OP_NEW_ARRAY.S */
1027    /*
1028     * Allocate an array of objects, specified with the array class
1029     * and a count.
1030     *
1031     * The verifier guarantees that this is an array class, so we don't
1032     * check for it here.
1033     */
1034    /* new-array vA, vB, class@CCCC */
1035    mov     r0, rINST, lsr #12          @ r0<- B
1036    FETCH(r2, 1)                        @ r2<- CCCC
1037    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1038    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1039    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1040    cmp     r1, #0                      @ check length
1041    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1042    bmi     common_errNegativeArraySize @ negative length, bail
1043    cmp     r0, #0                      @ already resolved?
1044    EXPORT_PC()                         @ req'd for resolve, alloc
1045    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1046    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1047
1048/* ------------------------------ */
1049    .balign 64
1050.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1051/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1052    /*
1053     * Create a new array with elements filled from registers.
1054     *
1055     * for: filled-new-array, filled-new-array/range
1056     */
1057    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1058    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1059    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1060    FETCH(r1, 1)                        @ r1<- BBBB
1061    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1062    EXPORT_PC()                         @ need for resolve and alloc
1063    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1064    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1065    cmp     r0, #0                      @ already resolved?
1066    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10678:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1068    mov     r2, #0                      @ r2<- false
1069    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1070    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1071    cmp     r0, #0                      @ got null?
1072    beq     common_exceptionThrown      @ yes, handle exception
1073    b       .LOP_FILLED_NEW_ARRAY_continue
1074
1075/* ------------------------------ */
1076    .balign 64
1077.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1078/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1079/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1080    /*
1081     * Create a new array with elements filled from registers.
1082     *
1083     * for: filled-new-array, filled-new-array/range
1084     */
1085    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1086    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1087    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1088    FETCH(r1, 1)                        @ r1<- BBBB
1089    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1090    EXPORT_PC()                         @ need for resolve and alloc
1091    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1092    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1093    cmp     r0, #0                      @ already resolved?
1094    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10958:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1096    mov     r2, #0                      @ r2<- false
1097    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1098    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1099    cmp     r0, #0                      @ got null?
1100    beq     common_exceptionThrown      @ yes, handle exception
1101    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1102
1103
1104/* ------------------------------ */
1105    .balign 64
1106.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1107/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1108    /* fill-array-data vAA, +BBBBBBBB */
1109    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1110    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1111    mov     r3, rINST, lsr #8           @ r3<- AA
1112    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1113    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1114    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1115    EXPORT_PC();
1116    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1117    cmp     r0, #0                      @ 0 means an exception is thrown
1118    beq     common_exceptionThrown      @ has exception
1119    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1120    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1121    GOTO_OPCODE(ip)                     @ jump to next instruction
1122
1123/* ------------------------------ */
1124    .balign 64
1125.L_OP_THROW: /* 0x27 */
1126/* File: armv5te/OP_THROW.S */
1127    /*
1128     * Throw an exception object in the current thread.
1129     */
1130    /* throw vAA */
1131    mov     r2, rINST, lsr #8           @ r2<- AA
1132    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1133    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
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/* ------------------------------ */
1142    .balign 64
1143.L_OP_GOTO: /* 0x28 */
1144/* File: armv5te/OP_GOTO.S */
1145    /*
1146     * Unconditional branch, 8-bit offset.
1147     *
1148     * The branch distance is a signed code-unit offset, which we need to
1149     * double to get a byte offset.
1150     */
1151    /* goto +AA */
1152    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1153    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1154    mov     r9, r9, lsl #1              @ r9<- byte offset
1155    bmi     common_backwardBranch       @ backward branch, do periodic checks
1156#if defined(WITH_JIT)
1157    GET_JIT_PROF_TABLE(r0)
1158    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1159    cmp     r0,#0
1160    bne     common_updateProfile
1161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1162    GOTO_OPCODE(ip)                     @ jump to next instruction
1163#else
1164    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1166    GOTO_OPCODE(ip)                     @ jump to next instruction
1167#endif
1168
1169/* ------------------------------ */
1170    .balign 64
1171.L_OP_GOTO_16: /* 0x29 */
1172/* File: armv5te/OP_GOTO_16.S */
1173    /*
1174     * Unconditional branch, 16-bit offset.
1175     *
1176     * The branch distance is a signed code-unit offset, which we need to
1177     * double to get a byte offset.
1178     */
1179    /* goto/16 +AAAA */
1180    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1181    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1182    bmi     common_backwardBranch       @ backward branch, do periodic checks
1183#if defined(WITH_JIT)
1184    GET_JIT_PROF_TABLE(r0)
1185    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1186    cmp     r0,#0
1187    bne     common_updateProfile
1188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1189    GOTO_OPCODE(ip)                     @ jump to next instruction
1190#else
1191    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1192    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1193    GOTO_OPCODE(ip)                     @ jump to next instruction
1194#endif
1195
1196
1197/* ------------------------------ */
1198    .balign 64
1199.L_OP_GOTO_32: /* 0x2a */
1200/* File: armv5te/OP_GOTO_32.S */
1201    /*
1202     * Unconditional branch, 32-bit offset.
1203     *
1204     * The branch distance is a signed code-unit offset, which we need to
1205     * double to get a byte offset.
1206     *
1207     * Unlike most opcodes, this one is allowed to branch to itself, so
1208     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1209     * instruction doesn't affect the V flag, so we need to clear it
1210     * explicitly.
1211     */
1212    /* goto/32 +AAAAAAAA */
1213    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1214    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1215    cmp     ip, ip                      @ (clear V flag during stall)
1216    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1217    mov     r9, r0, asl #1              @ r9<- byte offset
1218    ble     common_backwardBranch       @ backward branch, do periodic checks
1219#if defined(WITH_JIT)
1220    GET_JIT_PROF_TABLE(r0)
1221    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1222    cmp     r0,#0
1223    bne     common_updateProfile
1224    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1225    GOTO_OPCODE(ip)                     @ jump to next instruction
1226#else
1227    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1228    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1229    GOTO_OPCODE(ip)                     @ jump to next instruction
1230#endif
1231
1232/* ------------------------------ */
1233    .balign 64
1234.L_OP_PACKED_SWITCH: /* 0x2b */
1235/* File: armv5te/OP_PACKED_SWITCH.S */
1236    /*
1237     * Handle a packed-switch or sparse-switch instruction.  In both cases
1238     * we decode it and hand it off to a helper function.
1239     *
1240     * We don't really expect backward branches in a switch statement, but
1241     * they're perfectly legal, so we check for them here.
1242     *
1243     * for: packed-switch, sparse-switch
1244     */
1245    /* op vAA, +BBBB */
1246    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1247    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1248    mov     r3, rINST, lsr #8           @ r3<- AA
1249    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1250    GET_VREG(r1, r3)                    @ r1<- vAA
1251    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1252    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1253    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1254    bmi     common_backwardBranch       @ backward branch, do periodic checks
1255    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1256#if defined(WITH_JIT)
1257    GET_JIT_PROF_TABLE(r0)
1258    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1259    cmp     r0,#0
1260    bne     common_updateProfile
1261    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1262    GOTO_OPCODE(ip)                     @ jump to next instruction
1263#else
1264    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1265    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1266    GOTO_OPCODE(ip)                     @ jump to next instruction
1267#endif
1268
1269
1270/* ------------------------------ */
1271    .balign 64
1272.L_OP_SPARSE_SWITCH: /* 0x2c */
1273/* File: armv5te/OP_SPARSE_SWITCH.S */
1274/* File: armv5te/OP_PACKED_SWITCH.S */
1275    /*
1276     * Handle a packed-switch or sparse-switch instruction.  In both cases
1277     * we decode it and hand it off to a helper function.
1278     *
1279     * We don't really expect backward branches in a switch statement, but
1280     * they're perfectly legal, so we check for them here.
1281     *
1282     * for: packed-switch, sparse-switch
1283     */
1284    /* op vAA, +BBBB */
1285    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1286    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1287    mov     r3, rINST, lsr #8           @ r3<- AA
1288    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1289    GET_VREG(r1, r3)                    @ r1<- vAA
1290    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1291    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1292    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1293    bmi     common_backwardBranch       @ backward branch, do periodic checks
1294    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1295#if defined(WITH_JIT)
1296    GET_JIT_PROF_TABLE(r0)
1297    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1298    cmp     r0,#0
1299    bne     common_updateProfile
1300    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1301    GOTO_OPCODE(ip)                     @ jump to next instruction
1302#else
1303    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1305    GOTO_OPCODE(ip)                     @ jump to next instruction
1306#endif
1307
1308
1309
1310/* ------------------------------ */
1311    .balign 64
1312.L_OP_CMPL_FLOAT: /* 0x2d */
1313/* File: arm-vfp/OP_CMPL_FLOAT.S */
1314    /*
1315     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1316     * destination register based on the results of the comparison.
1317     *
1318     * int compare(x, y) {
1319     *     if (x == y) {
1320     *         return 0;
1321     *     } else if (x > y) {
1322     *         return 1;
1323     *     } else if (x < y) {
1324     *         return -1;
1325     *     } else {
1326     *         return -1;
1327     *     }
1328     * }
1329     */
1330    /* op vAA, vBB, vCC */
1331    FETCH(r0, 1)                        @ r0<- CCBB
1332    mov     r9, rINST, lsr #8           @ r9<- AA
1333    and     r2, r0, #255                @ r2<- BB
1334    mov     r3, r0, lsr #8              @ r3<- CC
1335    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1336    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1337    flds    s0, [r2]                    @ s0<- vBB
1338    flds    s1, [r3]                    @ s1<- vCC
1339    fcmpes  s0, s1                      @ compare (vBB, vCC)
1340    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1341    mvn     r0, #0                      @ r0<- -1 (default)
1342    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1343    fmstat                              @ export status flags
1344    movgt   r0, #1                      @ (greater than) r1<- 1
1345    moveq   r0, #0                      @ (equal) r1<- 0
1346    b       .LOP_CMPL_FLOAT_finish          @ argh
1347
1348
1349/* ------------------------------ */
1350    .balign 64
1351.L_OP_CMPG_FLOAT: /* 0x2e */
1352/* File: arm-vfp/OP_CMPG_FLOAT.S */
1353    /*
1354     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1355     * destination register based on the results of the comparison.
1356     *
1357     * int compare(x, y) {
1358     *     if (x == y) {
1359     *         return 0;
1360     *     } else if (x < y) {
1361     *         return -1;
1362     *     } else if (x > y) {
1363     *         return 1;
1364     *     } else {
1365     *         return 1;
1366     *     }
1367     * }
1368     */
1369    /* op vAA, vBB, vCC */
1370    FETCH(r0, 1)                        @ r0<- CCBB
1371    mov     r9, rINST, lsr #8           @ r9<- AA
1372    and     r2, r0, #255                @ r2<- BB
1373    mov     r3, r0, lsr #8              @ r3<- CC
1374    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1375    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1376    flds    s0, [r2]                    @ s0<- vBB
1377    flds    s1, [r3]                    @ s1<- vCC
1378    fcmpes  s0, s1                      @ compare (vBB, vCC)
1379    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1380    mov     r0, #1                      @ r0<- 1 (default)
1381    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1382    fmstat                              @ export status flags
1383    mvnmi   r0, #0                      @ (less than) r1<- -1
1384    moveq   r0, #0                      @ (equal) r1<- 0
1385    b       .LOP_CMPG_FLOAT_finish          @ argh
1386
1387
1388/* ------------------------------ */
1389    .balign 64
1390.L_OP_CMPL_DOUBLE: /* 0x2f */
1391/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1392    /*
1393     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1394     * destination register based on the results of the comparison.
1395     *
1396     * int compare(x, y) {
1397     *     if (x == y) {
1398     *         return 0;
1399     *     } else if (x > y) {
1400     *         return 1;
1401     *     } else if (x < y) {
1402     *         return -1;
1403     *     } else {
1404     *         return -1;
1405     *     }
1406     * }
1407     */
1408    /* op vAA, vBB, vCC */
1409    FETCH(r0, 1)                        @ r0<- CCBB
1410    mov     r9, rINST, lsr #8           @ r9<- AA
1411    and     r2, r0, #255                @ r2<- BB
1412    mov     r3, r0, lsr #8              @ r3<- CC
1413    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1414    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1415    fldd    d0, [r2]                    @ d0<- vBB
1416    fldd    d1, [r3]                    @ d1<- vCC
1417    fcmped  d0, d1                      @ compare (vBB, vCC)
1418    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1419    mvn     r0, #0                      @ r0<- -1 (default)
1420    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1421    fmstat                              @ export status flags
1422    movgt   r0, #1                      @ (greater than) r1<- 1
1423    moveq   r0, #0                      @ (equal) r1<- 0
1424    b       .LOP_CMPL_DOUBLE_finish          @ argh
1425
1426
1427/* ------------------------------ */
1428    .balign 64
1429.L_OP_CMPG_DOUBLE: /* 0x30 */
1430/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1431    /*
1432     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1433     * destination register based on the results of the comparison.
1434     *
1435     * int compare(x, y) {
1436     *     if (x == y) {
1437     *         return 0;
1438     *     } else if (x < y) {
1439     *         return -1;
1440     *     } else if (x > y) {
1441     *         return 1;
1442     *     } else {
1443     *         return 1;
1444     *     }
1445     * }
1446     */
1447    /* op vAA, vBB, vCC */
1448    FETCH(r0, 1)                        @ r0<- CCBB
1449    mov     r9, rINST, lsr #8           @ r9<- AA
1450    and     r2, r0, #255                @ r2<- BB
1451    mov     r3, r0, lsr #8              @ r3<- CC
1452    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1453    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1454    fldd    d0, [r2]                    @ d0<- vBB
1455    fldd    d1, [r3]                    @ d1<- vCC
1456    fcmped  d0, d1                      @ compare (vBB, vCC)
1457    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1458    mov     r0, #1                      @ r0<- 1 (default)
1459    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1460    fmstat                              @ export status flags
1461    mvnmi   r0, #0                      @ (less than) r1<- -1
1462    moveq   r0, #0                      @ (equal) r1<- 0
1463    b       .LOP_CMPG_DOUBLE_finish          @ argh
1464
1465
1466/* ------------------------------ */
1467    .balign 64
1468.L_OP_CMP_LONG: /* 0x31 */
1469/* File: armv5te/OP_CMP_LONG.S */
1470    /*
1471     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1472     * register based on the results of the comparison.
1473     *
1474     * We load the full values with LDM, but in practice many values could
1475     * be resolved by only looking at the high word.  This could be made
1476     * faster or slower by splitting the LDM into a pair of LDRs.
1477     *
1478     * If we just wanted to set condition flags, we could do this:
1479     *  subs    ip, r0, r2
1480     *  sbcs    ip, r1, r3
1481     *  subeqs  ip, r0, r2
1482     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1483     * integer value, which we can do with 2 conditional mov/mvn instructions
1484     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1485     * us a constant 5-cycle path plus a branch at the end to the
1486     * instruction epilogue code.  The multi-compare approach below needs
1487     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1488     * in the worst case (the 64-bit values are equal).
1489     */
1490    /* cmp-long vAA, vBB, vCC */
1491    FETCH(r0, 1)                        @ r0<- CCBB
1492    mov     r9, rINST, lsr #8           @ r9<- AA
1493    and     r2, r0, #255                @ r2<- BB
1494    mov     r3, r0, lsr #8              @ r3<- CC
1495    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1496    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1497    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1498    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1499    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1500    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1501    bgt     .LOP_CMP_LONG_greater
1502    subs    r1, r0, r2                  @ r1<- r0 - r2
1503    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1504    bne     .LOP_CMP_LONG_less
1505    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1506
1507/* ------------------------------ */
1508    .balign 64
1509.L_OP_IF_EQ: /* 0x32 */
1510/* File: armv6t2/OP_IF_EQ.S */
1511/* File: armv6t2/bincmp.S */
1512    /*
1513     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1514     * fragment that specifies the *reverse* comparison to perform, e.g.
1515     * for "if-le" you would use "gt".
1516     *
1517     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1518     */
1519    /* if-cmp vA, vB, +CCCC */
1520    mov     r1, rINST, lsr #12          @ r1<- B
1521    ubfx    r0, rINST, #8, #4           @ r0<- A
1522    GET_VREG(r3, r1)                    @ r3<- vB
1523    GET_VREG(r2, r0)                    @ r2<- vA
1524    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1525    cmp     r2, r3                      @ compare (vA, vB)
1526    bne  1f                      @ branch to 1 if comparison failed
1527    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1528    movs    r9, r9, asl #1              @ convert to bytes, check sign
1529    bmi     common_backwardBranch       @ yes, do periodic checks
15301:
1531#if defined(WITH_JIT)
1532    GET_JIT_PROF_TABLE(r0)
1533    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1534    b        common_testUpdateProfile
1535#else
1536    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1538    GOTO_OPCODE(ip)                     @ jump to next instruction
1539#endif
1540
1541
1542
1543/* ------------------------------ */
1544    .balign 64
1545.L_OP_IF_NE: /* 0x33 */
1546/* File: armv6t2/OP_IF_NE.S */
1547/* File: armv6t2/bincmp.S */
1548    /*
1549     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1550     * fragment that specifies the *reverse* comparison to perform, e.g.
1551     * for "if-le" you would use "gt".
1552     *
1553     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1554     */
1555    /* if-cmp vA, vB, +CCCC */
1556    mov     r1, rINST, lsr #12          @ r1<- B
1557    ubfx    r0, rINST, #8, #4           @ r0<- A
1558    GET_VREG(r3, r1)                    @ r3<- vB
1559    GET_VREG(r2, r0)                    @ r2<- vA
1560    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1561    cmp     r2, r3                      @ compare (vA, vB)
1562    beq  1f                      @ branch to 1 if comparison failed
1563    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1564    movs    r9, r9, asl #1              @ convert to bytes, check sign
1565    bmi     common_backwardBranch       @ yes, do periodic checks
15661:
1567#if defined(WITH_JIT)
1568    GET_JIT_PROF_TABLE(r0)
1569    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1570    b        common_testUpdateProfile
1571#else
1572    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1574    GOTO_OPCODE(ip)                     @ jump to next instruction
1575#endif
1576
1577
1578
1579/* ------------------------------ */
1580    .balign 64
1581.L_OP_IF_LT: /* 0x34 */
1582/* File: armv6t2/OP_IF_LT.S */
1583/* File: armv6t2/bincmp.S */
1584    /*
1585     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1586     * fragment that specifies the *reverse* comparison to perform, e.g.
1587     * for "if-le" you would use "gt".
1588     *
1589     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1590     */
1591    /* if-cmp vA, vB, +CCCC */
1592    mov     r1, rINST, lsr #12          @ r1<- B
1593    ubfx    r0, rINST, #8, #4           @ r0<- A
1594    GET_VREG(r3, r1)                    @ r3<- vB
1595    GET_VREG(r2, r0)                    @ r2<- vA
1596    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1597    cmp     r2, r3                      @ compare (vA, vB)
1598    bge  1f                      @ branch to 1 if comparison failed
1599    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1600    movs    r9, r9, asl #1              @ convert to bytes, check sign
1601    bmi     common_backwardBranch       @ yes, do periodic checks
16021:
1603#if defined(WITH_JIT)
1604    GET_JIT_PROF_TABLE(r0)
1605    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1606    b        common_testUpdateProfile
1607#else
1608    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1609    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1610    GOTO_OPCODE(ip)                     @ jump to next instruction
1611#endif
1612
1613
1614
1615/* ------------------------------ */
1616    .balign 64
1617.L_OP_IF_GE: /* 0x35 */
1618/* File: armv6t2/OP_IF_GE.S */
1619/* File: armv6t2/bincmp.S */
1620    /*
1621     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1622     * fragment that specifies the *reverse* comparison to perform, e.g.
1623     * for "if-le" you would use "gt".
1624     *
1625     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1626     */
1627    /* if-cmp vA, vB, +CCCC */
1628    mov     r1, rINST, lsr #12          @ r1<- B
1629    ubfx    r0, rINST, #8, #4           @ r0<- A
1630    GET_VREG(r3, r1)                    @ r3<- vB
1631    GET_VREG(r2, r0)                    @ r2<- vA
1632    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1633    cmp     r2, r3                      @ compare (vA, vB)
1634    blt  1f                      @ branch to 1 if comparison failed
1635    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1636    movs    r9, r9, asl #1              @ convert to bytes, check sign
1637    bmi     common_backwardBranch       @ yes, do periodic checks
16381:
1639#if defined(WITH_JIT)
1640    GET_JIT_PROF_TABLE(r0)
1641    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1642    b        common_testUpdateProfile
1643#else
1644    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1645    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1646    GOTO_OPCODE(ip)                     @ jump to next instruction
1647#endif
1648
1649
1650
1651/* ------------------------------ */
1652    .balign 64
1653.L_OP_IF_GT: /* 0x36 */
1654/* File: armv6t2/OP_IF_GT.S */
1655/* File: armv6t2/bincmp.S */
1656    /*
1657     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1658     * fragment that specifies the *reverse* comparison to perform, e.g.
1659     * for "if-le" you would use "gt".
1660     *
1661     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1662     */
1663    /* if-cmp vA, vB, +CCCC */
1664    mov     r1, rINST, lsr #12          @ r1<- B
1665    ubfx    r0, rINST, #8, #4           @ r0<- A
1666    GET_VREG(r3, r1)                    @ r3<- vB
1667    GET_VREG(r2, r0)                    @ r2<- vA
1668    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1669    cmp     r2, r3                      @ compare (vA, vB)
1670    ble  1f                      @ branch to 1 if comparison failed
1671    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1672    movs    r9, r9, asl #1              @ convert to bytes, check sign
1673    bmi     common_backwardBranch       @ yes, do periodic checks
16741:
1675#if defined(WITH_JIT)
1676    GET_JIT_PROF_TABLE(r0)
1677    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1678    b        common_testUpdateProfile
1679#else
1680    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1681    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1682    GOTO_OPCODE(ip)                     @ jump to next instruction
1683#endif
1684
1685
1686
1687/* ------------------------------ */
1688    .balign 64
1689.L_OP_IF_LE: /* 0x37 */
1690/* File: armv6t2/OP_IF_LE.S */
1691/* File: armv6t2/bincmp.S */
1692    /*
1693     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1694     * fragment that specifies the *reverse* comparison to perform, e.g.
1695     * for "if-le" you would use "gt".
1696     *
1697     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1698     */
1699    /* if-cmp vA, vB, +CCCC */
1700    mov     r1, rINST, lsr #12          @ r1<- B
1701    ubfx    r0, rINST, #8, #4           @ r0<- A
1702    GET_VREG(r3, r1)                    @ r3<- vB
1703    GET_VREG(r2, r0)                    @ r2<- vA
1704    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1705    cmp     r2, r3                      @ compare (vA, vB)
1706    bgt  1f                      @ branch to 1 if comparison failed
1707    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1708    movs    r9, r9, asl #1              @ convert to bytes, check sign
1709    bmi     common_backwardBranch       @ yes, do periodic checks
17101:
1711#if defined(WITH_JIT)
1712    GET_JIT_PROF_TABLE(r0)
1713    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1714    b        common_testUpdateProfile
1715#else
1716    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1717    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1718    GOTO_OPCODE(ip)                     @ jump to next instruction
1719#endif
1720
1721
1722
1723/* ------------------------------ */
1724    .balign 64
1725.L_OP_IF_EQZ: /* 0x38 */
1726/* File: armv5te/OP_IF_EQZ.S */
1727/* File: armv5te/zcmp.S */
1728    /*
1729     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1730     * fragment that specifies the *reverse* comparison to perform, e.g.
1731     * for "if-le" you would use "gt".
1732     *
1733     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1734     */
1735    /* if-cmp vAA, +BBBB */
1736    mov     r0, rINST, lsr #8           @ r0<- AA
1737    GET_VREG(r2, r0)                    @ r2<- vAA
1738    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1739    cmp     r2, #0                      @ compare (vA, 0)
1740    bne  1f                      @ branch to 1 if comparison failed
1741    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1742    movs    r9, r9, asl #1              @ convert to bytes, check sign
1743    bmi     common_backwardBranch       @ backward branch, do periodic checks
17441:
1745#if defined(WITH_JIT)
1746    GET_JIT_PROF_TABLE(r0)
1747    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1748    cmp     r0,#0
1749    bne     common_updateProfile
1750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1751    GOTO_OPCODE(ip)                     @ jump to next instruction
1752#else
1753    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1755    GOTO_OPCODE(ip)                     @ jump to next instruction
1756#endif
1757
1758
1759
1760/* ------------------------------ */
1761    .balign 64
1762.L_OP_IF_NEZ: /* 0x39 */
1763/* File: armv5te/OP_IF_NEZ.S */
1764/* File: armv5te/zcmp.S */
1765    /*
1766     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1767     * fragment that specifies the *reverse* comparison to perform, e.g.
1768     * for "if-le" you would use "gt".
1769     *
1770     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1771     */
1772    /* if-cmp vAA, +BBBB */
1773    mov     r0, rINST, lsr #8           @ r0<- AA
1774    GET_VREG(r2, r0)                    @ r2<- vAA
1775    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1776    cmp     r2, #0                      @ compare (vA, 0)
1777    beq  1f                      @ branch to 1 if comparison failed
1778    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1779    movs    r9, r9, asl #1              @ convert to bytes, check sign
1780    bmi     common_backwardBranch       @ backward branch, do periodic checks
17811:
1782#if defined(WITH_JIT)
1783    GET_JIT_PROF_TABLE(r0)
1784    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1785    cmp     r0,#0
1786    bne     common_updateProfile
1787    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1788    GOTO_OPCODE(ip)                     @ jump to next instruction
1789#else
1790    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1792    GOTO_OPCODE(ip)                     @ jump to next instruction
1793#endif
1794
1795
1796
1797/* ------------------------------ */
1798    .balign 64
1799.L_OP_IF_LTZ: /* 0x3a */
1800/* File: armv5te/OP_IF_LTZ.S */
1801/* File: armv5te/zcmp.S */
1802    /*
1803     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1804     * fragment that specifies the *reverse* comparison to perform, e.g.
1805     * for "if-le" you would use "gt".
1806     *
1807     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1808     */
1809    /* if-cmp vAA, +BBBB */
1810    mov     r0, rINST, lsr #8           @ r0<- AA
1811    GET_VREG(r2, r0)                    @ r2<- vAA
1812    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1813    cmp     r2, #0                      @ compare (vA, 0)
1814    bge  1f                      @ branch to 1 if comparison failed
1815    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1816    movs    r9, r9, asl #1              @ convert to bytes, check sign
1817    bmi     common_backwardBranch       @ backward branch, do periodic checks
18181:
1819#if defined(WITH_JIT)
1820    GET_JIT_PROF_TABLE(r0)
1821    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1822    cmp     r0,#0
1823    bne     common_updateProfile
1824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1825    GOTO_OPCODE(ip)                     @ jump to next instruction
1826#else
1827    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829    GOTO_OPCODE(ip)                     @ jump to next instruction
1830#endif
1831
1832
1833
1834/* ------------------------------ */
1835    .balign 64
1836.L_OP_IF_GEZ: /* 0x3b */
1837/* File: armv5te/OP_IF_GEZ.S */
1838/* File: armv5te/zcmp.S */
1839    /*
1840     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1841     * fragment that specifies the *reverse* comparison to perform, e.g.
1842     * for "if-le" you would use "gt".
1843     *
1844     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1845     */
1846    /* if-cmp vAA, +BBBB */
1847    mov     r0, rINST, lsr #8           @ r0<- AA
1848    GET_VREG(r2, r0)                    @ r2<- vAA
1849    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1850    cmp     r2, #0                      @ compare (vA, 0)
1851    blt  1f                      @ branch to 1 if comparison failed
1852    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1853    movs    r9, r9, asl #1              @ convert to bytes, check sign
1854    bmi     common_backwardBranch       @ backward branch, do periodic checks
18551:
1856#if defined(WITH_JIT)
1857    GET_JIT_PROF_TABLE(r0)
1858    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1859    cmp     r0,#0
1860    bne     common_updateProfile
1861    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1862    GOTO_OPCODE(ip)                     @ jump to next instruction
1863#else
1864    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1866    GOTO_OPCODE(ip)                     @ jump to next instruction
1867#endif
1868
1869
1870
1871/* ------------------------------ */
1872    .balign 64
1873.L_OP_IF_GTZ: /* 0x3c */
1874/* File: armv5te/OP_IF_GTZ.S */
1875/* File: armv5te/zcmp.S */
1876    /*
1877     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1878     * fragment that specifies the *reverse* comparison to perform, e.g.
1879     * for "if-le" you would use "gt".
1880     *
1881     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1882     */
1883    /* if-cmp vAA, +BBBB */
1884    mov     r0, rINST, lsr #8           @ r0<- AA
1885    GET_VREG(r2, r0)                    @ r2<- vAA
1886    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1887    cmp     r2, #0                      @ compare (vA, 0)
1888    ble  1f                      @ branch to 1 if comparison failed
1889    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1890    movs    r9, r9, asl #1              @ convert to bytes, check sign
1891    bmi     common_backwardBranch       @ backward branch, do periodic checks
18921:
1893#if defined(WITH_JIT)
1894    GET_JIT_PROF_TABLE(r0)
1895    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1896    cmp     r0,#0
1897    bne     common_updateProfile
1898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1899    GOTO_OPCODE(ip)                     @ jump to next instruction
1900#else
1901    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1902    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1903    GOTO_OPCODE(ip)                     @ jump to next instruction
1904#endif
1905
1906
1907
1908/* ------------------------------ */
1909    .balign 64
1910.L_OP_IF_LEZ: /* 0x3d */
1911/* File: armv5te/OP_IF_LEZ.S */
1912/* File: armv5te/zcmp.S */
1913    /*
1914     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1915     * fragment that specifies the *reverse* comparison to perform, e.g.
1916     * for "if-le" you would use "gt".
1917     *
1918     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1919     */
1920    /* if-cmp vAA, +BBBB */
1921    mov     r0, rINST, lsr #8           @ r0<- AA
1922    GET_VREG(r2, r0)                    @ r2<- vAA
1923    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1924    cmp     r2, #0                      @ compare (vA, 0)
1925    bgt  1f                      @ branch to 1 if comparison failed
1926    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1927    movs    r9, r9, asl #1              @ convert to bytes, check sign
1928    bmi     common_backwardBranch       @ backward branch, do periodic checks
19291:
1930#if defined(WITH_JIT)
1931    GET_JIT_PROF_TABLE(r0)
1932    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1933    cmp     r0,#0
1934    bne     common_updateProfile
1935    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1936    GOTO_OPCODE(ip)                     @ jump to next instruction
1937#else
1938    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1940    GOTO_OPCODE(ip)                     @ jump to next instruction
1941#endif
1942
1943
1944
1945/* ------------------------------ */
1946    .balign 64
1947.L_OP_UNUSED_3E: /* 0x3e */
1948/* File: armv5te/OP_UNUSED_3E.S */
1949/* File: armv5te/unused.S */
1950    bl      common_abort
1951
1952
1953
1954/* ------------------------------ */
1955    .balign 64
1956.L_OP_UNUSED_3F: /* 0x3f */
1957/* File: armv5te/OP_UNUSED_3F.S */
1958/* File: armv5te/unused.S */
1959    bl      common_abort
1960
1961
1962
1963/* ------------------------------ */
1964    .balign 64
1965.L_OP_UNUSED_40: /* 0x40 */
1966/* File: armv5te/OP_UNUSED_40.S */
1967/* File: armv5te/unused.S */
1968    bl      common_abort
1969
1970
1971
1972/* ------------------------------ */
1973    .balign 64
1974.L_OP_UNUSED_41: /* 0x41 */
1975/* File: armv5te/OP_UNUSED_41.S */
1976/* File: armv5te/unused.S */
1977    bl      common_abort
1978
1979
1980
1981/* ------------------------------ */
1982    .balign 64
1983.L_OP_UNUSED_42: /* 0x42 */
1984/* File: armv5te/OP_UNUSED_42.S */
1985/* File: armv5te/unused.S */
1986    bl      common_abort
1987
1988
1989
1990/* ------------------------------ */
1991    .balign 64
1992.L_OP_UNUSED_43: /* 0x43 */
1993/* File: armv5te/OP_UNUSED_43.S */
1994/* File: armv5te/unused.S */
1995    bl      common_abort
1996
1997
1998
1999/* ------------------------------ */
2000    .balign 64
2001.L_OP_AGET: /* 0x44 */
2002/* File: armv5te/OP_AGET.S */
2003    /*
2004     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2005     *
2006     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2007     * instructions.  We use a pair of FETCH_Bs instead.
2008     *
2009     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2010     */
2011    /* op vAA, vBB, vCC */
2012    FETCH_B(r2, 1, 0)                   @ r2<- BB
2013    mov     r9, rINST, lsr #8           @ r9<- AA
2014    FETCH_B(r3, 1, 1)                   @ r3<- CC
2015    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2016    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2017    cmp     r0, #0                      @ null array object?
2018    beq     common_errNullObject        @ yes, bail
2019    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2020    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2021    cmp     r1, r3                      @ compare unsigned index, length
2022    bcs     common_errArrayIndex        @ index >= length, bail
2023    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2024    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2025    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2026    SET_VREG(r2, r9)                    @ vAA<- r2
2027    GOTO_OPCODE(ip)                     @ jump to next instruction
2028
2029
2030/* ------------------------------ */
2031    .balign 64
2032.L_OP_AGET_WIDE: /* 0x45 */
2033/* File: armv5te/OP_AGET_WIDE.S */
2034    /*
2035     * Array get, 64 bits.  vAA <- vBB[vCC].
2036     *
2037     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2038     */
2039    /* aget-wide vAA, vBB, vCC */
2040    FETCH(r0, 1)                        @ r0<- CCBB
2041    mov     r9, rINST, lsr #8           @ r9<- AA
2042    and     r2, r0, #255                @ r2<- BB
2043    mov     r3, r0, lsr #8              @ r3<- CC
2044    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2045    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2046    cmp     r0, #0                      @ null array object?
2047    beq     common_errNullObject        @ yes, bail
2048    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2049    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2050    cmp     r1, r3                      @ compare unsigned index, length
2051    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2052    b       common_errArrayIndex        @ index >= length, bail
2053    @ May want to swap the order of these two branches depending on how the
2054    @ branch prediction (if any) handles conditional forward branches vs.
2055    @ unconditional forward branches.
2056
2057/* ------------------------------ */
2058    .balign 64
2059.L_OP_AGET_OBJECT: /* 0x46 */
2060/* File: armv5te/OP_AGET_OBJECT.S */
2061/* File: armv5te/OP_AGET.S */
2062    /*
2063     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2064     *
2065     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2066     * instructions.  We use a pair of FETCH_Bs instead.
2067     *
2068     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2069     */
2070    /* op vAA, vBB, vCC */
2071    FETCH_B(r2, 1, 0)                   @ r2<- BB
2072    mov     r9, rINST, lsr #8           @ r9<- AA
2073    FETCH_B(r3, 1, 1)                   @ r3<- CC
2074    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2075    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2076    cmp     r0, #0                      @ null array object?
2077    beq     common_errNullObject        @ yes, bail
2078    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2079    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2080    cmp     r1, r3                      @ compare unsigned index, length
2081    bcs     common_errArrayIndex        @ index >= length, bail
2082    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2083    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2084    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2085    SET_VREG(r2, r9)                    @ vAA<- r2
2086    GOTO_OPCODE(ip)                     @ jump to next instruction
2087
2088
2089
2090/* ------------------------------ */
2091    .balign 64
2092.L_OP_AGET_BOOLEAN: /* 0x47 */
2093/* File: armv5te/OP_AGET_BOOLEAN.S */
2094/* File: armv5te/OP_AGET.S */
2095    /*
2096     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2097     *
2098     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2099     * instructions.  We use a pair of FETCH_Bs instead.
2100     *
2101     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2102     */
2103    /* op vAA, vBB, vCC */
2104    FETCH_B(r2, 1, 0)                   @ r2<- BB
2105    mov     r9, rINST, lsr #8           @ r9<- AA
2106    FETCH_B(r3, 1, 1)                   @ r3<- CC
2107    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2108    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2109    cmp     r0, #0                      @ null array object?
2110    beq     common_errNullObject        @ yes, bail
2111    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2112    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2113    cmp     r1, r3                      @ compare unsigned index, length
2114    bcs     common_errArrayIndex        @ index >= length, bail
2115    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2116    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2117    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2118    SET_VREG(r2, r9)                    @ vAA<- r2
2119    GOTO_OPCODE(ip)                     @ jump to next instruction
2120
2121
2122
2123/* ------------------------------ */
2124    .balign 64
2125.L_OP_AGET_BYTE: /* 0x48 */
2126/* File: armv5te/OP_AGET_BYTE.S */
2127/* File: armv5te/OP_AGET.S */
2128    /*
2129     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2130     *
2131     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2132     * instructions.  We use a pair of FETCH_Bs instead.
2133     *
2134     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2135     */
2136    /* op vAA, vBB, vCC */
2137    FETCH_B(r2, 1, 0)                   @ r2<- BB
2138    mov     r9, rINST, lsr #8           @ r9<- AA
2139    FETCH_B(r3, 1, 1)                   @ r3<- CC
2140    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2141    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2142    cmp     r0, #0                      @ null array object?
2143    beq     common_errNullObject        @ yes, bail
2144    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2145    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2146    cmp     r1, r3                      @ compare unsigned index, length
2147    bcs     common_errArrayIndex        @ index >= length, bail
2148    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2149    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2150    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2151    SET_VREG(r2, r9)                    @ vAA<- r2
2152    GOTO_OPCODE(ip)                     @ jump to next instruction
2153
2154
2155
2156/* ------------------------------ */
2157    .balign 64
2158.L_OP_AGET_CHAR: /* 0x49 */
2159/* File: armv5te/OP_AGET_CHAR.S */
2160/* File: armv5te/OP_AGET.S */
2161    /*
2162     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2163     *
2164     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2165     * instructions.  We use a pair of FETCH_Bs instead.
2166     *
2167     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2168     */
2169    /* op vAA, vBB, vCC */
2170    FETCH_B(r2, 1, 0)                   @ r2<- BB
2171    mov     r9, rINST, lsr #8           @ r9<- AA
2172    FETCH_B(r3, 1, 1)                   @ r3<- CC
2173    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2174    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2175    cmp     r0, #0                      @ null array object?
2176    beq     common_errNullObject        @ yes, bail
2177    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2178    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2179    cmp     r1, r3                      @ compare unsigned index, length
2180    bcs     common_errArrayIndex        @ index >= length, bail
2181    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2182    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2183    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2184    SET_VREG(r2, r9)                    @ vAA<- r2
2185    GOTO_OPCODE(ip)                     @ jump to next instruction
2186
2187
2188
2189/* ------------------------------ */
2190    .balign 64
2191.L_OP_AGET_SHORT: /* 0x4a */
2192/* File: armv5te/OP_AGET_SHORT.S */
2193/* File: armv5te/OP_AGET.S */
2194    /*
2195     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2196     *
2197     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2198     * instructions.  We use a pair of FETCH_Bs instead.
2199     *
2200     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2201     */
2202    /* op vAA, vBB, vCC */
2203    FETCH_B(r2, 1, 0)                   @ r2<- BB
2204    mov     r9, rINST, lsr #8           @ r9<- AA
2205    FETCH_B(r3, 1, 1)                   @ r3<- CC
2206    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2207    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2208    cmp     r0, #0                      @ null array object?
2209    beq     common_errNullObject        @ yes, bail
2210    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2211    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2212    cmp     r1, r3                      @ compare unsigned index, length
2213    bcs     common_errArrayIndex        @ index >= length, bail
2214    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2215    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2217    SET_VREG(r2, r9)                    @ vAA<- r2
2218    GOTO_OPCODE(ip)                     @ jump to next instruction
2219
2220
2221
2222/* ------------------------------ */
2223    .balign 64
2224.L_OP_APUT: /* 0x4b */
2225/* File: armv5te/OP_APUT.S */
2226    /*
2227     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2228     *
2229     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2230     * instructions.  We use a pair of FETCH_Bs instead.
2231     *
2232     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2233     */
2234    /* op vAA, vBB, vCC */
2235    FETCH_B(r2, 1, 0)                   @ r2<- BB
2236    mov     r9, rINST, lsr #8           @ r9<- AA
2237    FETCH_B(r3, 1, 1)                   @ 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 #2     @ r0<- arrayObj + index*width
2244    cmp     r1, r3                      @ compare unsigned index, length
2245    bcs     common_errArrayIndex        @ index >= length, bail
2246    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2247    GET_VREG(r2, r9)                    @ r2<- vAA
2248    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2249    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2250    GOTO_OPCODE(ip)                     @ jump to next instruction
2251
2252
2253/* ------------------------------ */
2254    .balign 64
2255.L_OP_APUT_WIDE: /* 0x4c */
2256/* File: armv5te/OP_APUT_WIDE.S */
2257    /*
2258     * Array put, 64 bits.  vBB[vCC] <- vAA.
2259     *
2260     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2261     */
2262    /* aput-wide 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(r0, r2)                    @ r0<- vBB (array object)
2268    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2269    cmp     r0, #0                      @ null array object?
2270    beq     common_errNullObject        @ yes, bail
2271    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2272    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2273    cmp     r1, r3                      @ compare unsigned index, length
2274    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2275    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2276    b       common_errArrayIndex        @ index >= length, bail
2277    @ May want to swap the order of these two branches depending on how the
2278    @ branch prediction (if any) handles conditional forward branches vs.
2279    @ unconditional forward branches.
2280
2281/* ------------------------------ */
2282    .balign 64
2283.L_OP_APUT_OBJECT: /* 0x4d */
2284/* File: armv5te/OP_APUT_OBJECT.S */
2285    /*
2286     * Store an object into an array.  vBB[vCC] <- vAA.
2287     *
2288     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2289     * instructions.  We use a pair of FETCH_Bs instead.
2290     */
2291    /* op vAA, vBB, vCC */
2292    FETCH(r0, 1)                        @ r0<- CCBB
2293    mov     r9, rINST, lsr #8           @ r9<- AA
2294    and     r2, r0, #255                @ r2<- BB
2295    mov     r3, r0, lsr #8              @ r3<- CC
2296    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2297    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2298    cmp     r1, #0                      @ null array object?
2299    GET_VREG(r9, r9)                    @ r9<- vAA
2300    beq     common_errNullObject        @ yes, bail
2301    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2302    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2303    cmp     r0, r3                      @ compare unsigned index, length
2304    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2305    b       common_errArrayIndex        @ index >= length, bail
2306
2307
2308/* ------------------------------ */
2309    .balign 64
2310.L_OP_APUT_BOOLEAN: /* 0x4e */
2311/* File: armv5te/OP_APUT_BOOLEAN.S */
2312/* File: armv5te/OP_APUT.S */
2313    /*
2314     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2315     *
2316     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2317     * instructions.  We use a pair of FETCH_Bs instead.
2318     *
2319     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2320     */
2321    /* op vAA, vBB, vCC */
2322    FETCH_B(r2, 1, 0)                   @ r2<- BB
2323    mov     r9, rINST, lsr #8           @ r9<- AA
2324    FETCH_B(r3, 1, 1)                   @ r3<- CC
2325    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2326    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2327    cmp     r0, #0                      @ null array object?
2328    beq     common_errNullObject        @ yes, bail
2329    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2330    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2331    cmp     r1, r3                      @ compare unsigned index, length
2332    bcs     common_errArrayIndex        @ index >= length, bail
2333    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2334    GET_VREG(r2, r9)                    @ r2<- vAA
2335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2336    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2337    GOTO_OPCODE(ip)                     @ jump to next instruction
2338
2339
2340
2341/* ------------------------------ */
2342    .balign 64
2343.L_OP_APUT_BYTE: /* 0x4f */
2344/* File: armv5te/OP_APUT_BYTE.S */
2345/* File: armv5te/OP_APUT.S */
2346    /*
2347     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2348     *
2349     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2350     * instructions.  We use a pair of FETCH_Bs instead.
2351     *
2352     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2353     */
2354    /* op vAA, vBB, vCC */
2355    FETCH_B(r2, 1, 0)                   @ r2<- BB
2356    mov     r9, rINST, lsr #8           @ r9<- AA
2357    FETCH_B(r3, 1, 1)                   @ r3<- CC
2358    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2359    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2360    cmp     r0, #0                      @ null array object?
2361    beq     common_errNullObject        @ yes, bail
2362    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2363    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2364    cmp     r1, r3                      @ compare unsigned index, length
2365    bcs     common_errArrayIndex        @ index >= length, bail
2366    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2367    GET_VREG(r2, r9)                    @ r2<- vAA
2368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2369    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2370    GOTO_OPCODE(ip)                     @ jump to next instruction
2371
2372
2373
2374/* ------------------------------ */
2375    .balign 64
2376.L_OP_APUT_CHAR: /* 0x50 */
2377/* File: armv5te/OP_APUT_CHAR.S */
2378/* File: armv5te/OP_APUT.S */
2379    /*
2380     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2381     *
2382     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2383     * instructions.  We use a pair of FETCH_Bs instead.
2384     *
2385     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2386     */
2387    /* op vAA, vBB, vCC */
2388    FETCH_B(r2, 1, 0)                   @ r2<- BB
2389    mov     r9, rINST, lsr #8           @ r9<- AA
2390    FETCH_B(r3, 1, 1)                   @ r3<- CC
2391    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2392    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2393    cmp     r0, #0                      @ null array object?
2394    beq     common_errNullObject        @ yes, bail
2395    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2396    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2397    cmp     r1, r3                      @ compare unsigned index, length
2398    bcs     common_errArrayIndex        @ index >= length, bail
2399    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2400    GET_VREG(r2, r9)                    @ r2<- vAA
2401    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2402    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2403    GOTO_OPCODE(ip)                     @ jump to next instruction
2404
2405
2406
2407/* ------------------------------ */
2408    .balign 64
2409.L_OP_APUT_SHORT: /* 0x51 */
2410/* File: armv5te/OP_APUT_SHORT.S */
2411/* File: armv5te/OP_APUT.S */
2412    /*
2413     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2414     *
2415     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2416     * instructions.  We use a pair of FETCH_Bs instead.
2417     *
2418     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2419     */
2420    /* op vAA, vBB, vCC */
2421    FETCH_B(r2, 1, 0)                   @ r2<- BB
2422    mov     r9, rINST, lsr #8           @ r9<- AA
2423    FETCH_B(r3, 1, 1)                   @ r3<- CC
2424    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2425    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2426    cmp     r0, #0                      @ null array object?
2427    beq     common_errNullObject        @ yes, bail
2428    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2429    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2430    cmp     r1, r3                      @ compare unsigned index, length
2431    bcs     common_errArrayIndex        @ index >= length, bail
2432    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2433    GET_VREG(r2, r9)                    @ r2<- vAA
2434    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2435    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2436    GOTO_OPCODE(ip)                     @ jump to next instruction
2437
2438
2439
2440/* ------------------------------ */
2441    .balign 64
2442.L_OP_IGET: /* 0x52 */
2443/* File: armv6t2/OP_IGET.S */
2444    /*
2445     * General 32-bit instance field get.
2446     *
2447     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2448     */
2449    /* op vA, vB, field@CCCC */
2450    mov     r0, rINST, lsr #12          @ r0<- B
2451    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2452    FETCH(r1, 1)                        @ r1<- field ref CCCC
2453    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2454    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2455    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2456    cmp     r0, #0                      @ is resolved entry null?
2457    bne     .LOP_IGET_finish          @ no, already resolved
24588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2459    EXPORT_PC()                         @ resolve() could throw
2460    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2461    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2462    cmp     r0, #0
2463    bne     .LOP_IGET_finish
2464    b       common_exceptionThrown
2465
2466/* ------------------------------ */
2467    .balign 64
2468.L_OP_IGET_WIDE: /* 0x53 */
2469/* File: armv6t2/OP_IGET_WIDE.S */
2470    /*
2471     * Wide 32-bit instance field get.
2472     */
2473    /* iget-wide vA, vB, field@CCCC */
2474    mov     r0, rINST, lsr #12          @ r0<- B
2475    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2476    FETCH(r1, 1)                        @ r1<- field ref CCCC
2477    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2478    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2479    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2480    cmp     r0, #0                      @ is resolved entry null?
2481    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24828:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2483    EXPORT_PC()                         @ resolve() could throw
2484    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2485    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2486    cmp     r0, #0
2487    bne     .LOP_IGET_WIDE_finish
2488    b       common_exceptionThrown
2489
2490/* ------------------------------ */
2491    .balign 64
2492.L_OP_IGET_OBJECT: /* 0x54 */
2493/* File: armv5te/OP_IGET_OBJECT.S */
2494/* File: armv5te/OP_IGET.S */
2495    /*
2496     * General 32-bit instance field get.
2497     *
2498     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2499     */
2500    /* op vA, vB, field@CCCC */
2501    mov     r0, rINST, lsr #12          @ r0<- B
2502    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2503    FETCH(r1, 1)                        @ r1<- field ref CCCC
2504    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2505    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2506    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2507    cmp     r0, #0                      @ is resolved entry null?
2508    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25098:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2510    EXPORT_PC()                         @ resolve() could throw
2511    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2512    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2513    cmp     r0, #0
2514    bne     .LOP_IGET_OBJECT_finish
2515    b       common_exceptionThrown
2516
2517
2518/* ------------------------------ */
2519    .balign 64
2520.L_OP_IGET_BOOLEAN: /* 0x55 */
2521/* File: armv5te/OP_IGET_BOOLEAN.S */
2522@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2523/* File: armv5te/OP_IGET.S */
2524    /*
2525     * General 32-bit instance field get.
2526     *
2527     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2528     */
2529    /* op vA, vB, field@CCCC */
2530    mov     r0, rINST, lsr #12          @ r0<- B
2531    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2532    FETCH(r1, 1)                        @ r1<- field ref CCCC
2533    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2534    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2535    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2536    cmp     r0, #0                      @ is resolved entry null?
2537    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25388:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2539    EXPORT_PC()                         @ resolve() could throw
2540    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2541    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2542    cmp     r0, #0
2543    bne     .LOP_IGET_BOOLEAN_finish
2544    b       common_exceptionThrown
2545
2546
2547/* ------------------------------ */
2548    .balign 64
2549.L_OP_IGET_BYTE: /* 0x56 */
2550/* File: armv5te/OP_IGET_BYTE.S */
2551@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2552/* File: armv5te/OP_IGET.S */
2553    /*
2554     * General 32-bit instance field get.
2555     *
2556     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2557     */
2558    /* op vA, vB, field@CCCC */
2559    mov     r0, rINST, lsr #12          @ r0<- B
2560    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2561    FETCH(r1, 1)                        @ r1<- field ref CCCC
2562    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2563    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2564    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2565    cmp     r0, #0                      @ is resolved entry null?
2566    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25678:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2568    EXPORT_PC()                         @ resolve() could throw
2569    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2570    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2571    cmp     r0, #0
2572    bne     .LOP_IGET_BYTE_finish
2573    b       common_exceptionThrown
2574
2575
2576/* ------------------------------ */
2577    .balign 64
2578.L_OP_IGET_CHAR: /* 0x57 */
2579/* File: armv5te/OP_IGET_CHAR.S */
2580@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2581/* File: armv5te/OP_IGET.S */
2582    /*
2583     * General 32-bit instance field get.
2584     *
2585     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2586     */
2587    /* op vA, vB, field@CCCC */
2588    mov     r0, rINST, lsr #12          @ r0<- B
2589    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2590    FETCH(r1, 1)                        @ r1<- field ref CCCC
2591    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2592    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2593    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2594    cmp     r0, #0                      @ is resolved entry null?
2595    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25968:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2597    EXPORT_PC()                         @ resolve() could throw
2598    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2599    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2600    cmp     r0, #0
2601    bne     .LOP_IGET_CHAR_finish
2602    b       common_exceptionThrown
2603
2604
2605/* ------------------------------ */
2606    .balign 64
2607.L_OP_IGET_SHORT: /* 0x58 */
2608/* File: armv5te/OP_IGET_SHORT.S */
2609@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2610/* File: armv5te/OP_IGET.S */
2611    /*
2612     * General 32-bit instance field get.
2613     *
2614     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2615     */
2616    /* op vA, vB, field@CCCC */
2617    mov     r0, rINST, lsr #12          @ r0<- B
2618    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2619    FETCH(r1, 1)                        @ r1<- field ref CCCC
2620    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2621    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2622    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2623    cmp     r0, #0                      @ is resolved entry null?
2624    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26258:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2626    EXPORT_PC()                         @ resolve() could throw
2627    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2628    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2629    cmp     r0, #0
2630    bne     .LOP_IGET_SHORT_finish
2631    b       common_exceptionThrown
2632
2633
2634/* ------------------------------ */
2635    .balign 64
2636.L_OP_IPUT: /* 0x59 */
2637/* File: armv6t2/OP_IPUT.S */
2638    /*
2639     * General 32-bit instance field put.
2640     *
2641     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2642     */
2643    /* op vA, vB, field@CCCC */
2644    mov     r0, rINST, lsr #12          @ r0<- B
2645    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2646    FETCH(r1, 1)                        @ r1<- field ref CCCC
2647    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2648    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2649    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2650    cmp     r0, #0                      @ is resolved entry null?
2651    bne     .LOP_IPUT_finish          @ no, already resolved
26528:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2653    EXPORT_PC()                         @ resolve() could throw
2654    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2655    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2656    cmp     r0, #0                      @ success?
2657    bne     .LOP_IPUT_finish          @ yes, finish up
2658    b       common_exceptionThrown
2659
2660/* ------------------------------ */
2661    .balign 64
2662.L_OP_IPUT_WIDE: /* 0x5a */
2663/* File: armv6t2/OP_IPUT_WIDE.S */
2664    /* iput-wide vA, vB, field@CCCC */
2665    mov     r0, rINST, lsr #12          @ r0<- B
2666    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2667    FETCH(r1, 1)                        @ r1<- field ref CCCC
2668    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2669    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2670    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2671    cmp     r0, #0                      @ is resolved entry null?
2672    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26738:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2674    EXPORT_PC()                         @ resolve() could throw
2675    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2676    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2677    cmp     r0, #0                      @ success?
2678    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2679    b       common_exceptionThrown
2680
2681/* ------------------------------ */
2682    .balign 64
2683.L_OP_IPUT_OBJECT: /* 0x5b */
2684/* File: armv5te/OP_IPUT_OBJECT.S */
2685/* File: armv5te/OP_IPUT.S */
2686    /*
2687     * General 32-bit instance field put.
2688     *
2689     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2690     */
2691    /* op vA, vB, field@CCCC */
2692    mov     r0, rINST, lsr #12          @ r0<- B
2693    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2694    FETCH(r1, 1)                        @ r1<- field ref CCCC
2695    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2696    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2697    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2698    cmp     r0, #0                      @ is resolved entry null?
2699    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
27008:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2701    EXPORT_PC()                         @ resolve() could throw
2702    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2703    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2704    cmp     r0, #0                      @ success?
2705    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2706    b       common_exceptionThrown
2707
2708
2709/* ------------------------------ */
2710    .balign 64
2711.L_OP_IPUT_BOOLEAN: /* 0x5c */
2712/* File: armv5te/OP_IPUT_BOOLEAN.S */
2713@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2714/* File: armv5te/OP_IPUT.S */
2715    /*
2716     * General 32-bit instance field put.
2717     *
2718     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2719     */
2720    /* op vA, vB, field@CCCC */
2721    mov     r0, rINST, lsr #12          @ r0<- B
2722    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2723    FETCH(r1, 1)                        @ r1<- field ref CCCC
2724    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2725    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2726    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2727    cmp     r0, #0                      @ is resolved entry null?
2728    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2730    EXPORT_PC()                         @ resolve() could throw
2731    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2732    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2733    cmp     r0, #0                      @ success?
2734    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2735    b       common_exceptionThrown
2736
2737
2738/* ------------------------------ */
2739    .balign 64
2740.L_OP_IPUT_BYTE: /* 0x5d */
2741/* File: armv5te/OP_IPUT_BYTE.S */
2742@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2743/* File: armv5te/OP_IPUT.S */
2744    /*
2745     * General 32-bit instance field put.
2746     *
2747     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2748     */
2749    /* op vA, vB, field@CCCC */
2750    mov     r0, rINST, lsr #12          @ r0<- B
2751    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2752    FETCH(r1, 1)                        @ r1<- field ref CCCC
2753    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2754    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2755    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2756    cmp     r0, #0                      @ is resolved entry null?
2757    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2759    EXPORT_PC()                         @ resolve() could throw
2760    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2761    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2762    cmp     r0, #0                      @ success?
2763    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2764    b       common_exceptionThrown
2765
2766
2767/* ------------------------------ */
2768    .balign 64
2769.L_OP_IPUT_CHAR: /* 0x5e */
2770/* File: armv5te/OP_IPUT_CHAR.S */
2771@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2772/* File: armv5te/OP_IPUT.S */
2773    /*
2774     * General 32-bit instance field put.
2775     *
2776     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2777     */
2778    /* op vA, vB, field@CCCC */
2779    mov     r0, rINST, lsr #12          @ r0<- B
2780    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2781    FETCH(r1, 1)                        @ r1<- field ref CCCC
2782    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2783    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2784    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2785    cmp     r0, #0                      @ is resolved entry null?
2786    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27878:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2788    EXPORT_PC()                         @ resolve() could throw
2789    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2790    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2791    cmp     r0, #0                      @ success?
2792    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2793    b       common_exceptionThrown
2794
2795
2796/* ------------------------------ */
2797    .balign 64
2798.L_OP_IPUT_SHORT: /* 0x5f */
2799/* File: armv5te/OP_IPUT_SHORT.S */
2800@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2801/* File: armv5te/OP_IPUT.S */
2802    /*
2803     * General 32-bit instance field put.
2804     *
2805     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2806     */
2807    /* op vA, vB, field@CCCC */
2808    mov     r0, rINST, lsr #12          @ r0<- B
2809    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2810    FETCH(r1, 1)                        @ r1<- field ref CCCC
2811    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2812    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2813    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2814    cmp     r0, #0                      @ is resolved entry null?
2815    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28168:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2817    EXPORT_PC()                         @ resolve() could throw
2818    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2819    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2820    cmp     r0, #0                      @ success?
2821    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2822    b       common_exceptionThrown
2823
2824
2825/* ------------------------------ */
2826    .balign 64
2827.L_OP_SGET: /* 0x60 */
2828/* File: armv5te/OP_SGET.S */
2829    /*
2830     * General 32-bit SGET handler.
2831     *
2832     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2833     */
2834    /* op vAA, field@BBBB */
2835    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2836    FETCH(r1, 1)                        @ r1<- field ref BBBB
2837    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2838    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2839    cmp     r0, #0                      @ is resolved entry null?
2840    beq     .LOP_SGET_resolve         @ yes, do resolve
2841.LOP_SGET_finish: @ field ptr in r0
2842    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2843    mov     r2, rINST, lsr #8           @ r2<- AA
2844    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2845    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2846    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2847    GOTO_OPCODE(ip)                     @ jump to next instruction
2848
2849/* ------------------------------ */
2850    .balign 64
2851.L_OP_SGET_WIDE: /* 0x61 */
2852/* File: armv5te/OP_SGET_WIDE.S */
2853    /*
2854     * 64-bit SGET handler.
2855     */
2856    /* sget-wide vAA, field@BBBB */
2857    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2858    FETCH(r1, 1)                        @ r1<- field ref BBBB
2859    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2860    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2861    cmp     r0, #0                      @ is resolved entry null?
2862    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2863.LOP_SGET_WIDE_finish:
2864    mov     r9, rINST, lsr #8           @ r9<- AA
2865    .if 0
2866    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2867    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
2868    .else
2869    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2870    .endif
2871    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2872    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2873    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2874    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2875    GOTO_OPCODE(ip)                     @ jump to next instruction
2876
2877/* ------------------------------ */
2878    .balign 64
2879.L_OP_SGET_OBJECT: /* 0x62 */
2880/* File: armv5te/OP_SGET_OBJECT.S */
2881/* File: armv5te/OP_SGET.S */
2882    /*
2883     * General 32-bit SGET handler.
2884     *
2885     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2886     */
2887    /* op vAA, field@BBBB */
2888    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2889    FETCH(r1, 1)                        @ r1<- field ref BBBB
2890    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2891    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2892    cmp     r0, #0                      @ is resolved entry null?
2893    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2894.LOP_SGET_OBJECT_finish: @ field ptr in r0
2895    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2896    mov     r2, rINST, lsr #8           @ r2<- AA
2897    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2898    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2899    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2900    GOTO_OPCODE(ip)                     @ jump to next instruction
2901
2902
2903/* ------------------------------ */
2904    .balign 64
2905.L_OP_SGET_BOOLEAN: /* 0x63 */
2906/* File: armv5te/OP_SGET_BOOLEAN.S */
2907/* File: armv5te/OP_SGET.S */
2908    /*
2909     * General 32-bit SGET handler.
2910     *
2911     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2912     */
2913    /* op vAA, field@BBBB */
2914    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2915    FETCH(r1, 1)                        @ r1<- field ref BBBB
2916    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2917    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2918    cmp     r0, #0                      @ is resolved entry null?
2919    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2920.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2921    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2922    mov     r2, rINST, lsr #8           @ r2<- AA
2923    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2924    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2925    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2926    GOTO_OPCODE(ip)                     @ jump to next instruction
2927
2928
2929/* ------------------------------ */
2930    .balign 64
2931.L_OP_SGET_BYTE: /* 0x64 */
2932/* File: armv5te/OP_SGET_BYTE.S */
2933/* File: armv5te/OP_SGET.S */
2934    /*
2935     * General 32-bit SGET handler.
2936     *
2937     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2938     */
2939    /* op vAA, field@BBBB */
2940    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2941    FETCH(r1, 1)                        @ r1<- field ref BBBB
2942    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2943    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2944    cmp     r0, #0                      @ is resolved entry null?
2945    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2946.LOP_SGET_BYTE_finish: @ field ptr in r0
2947    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2948    mov     r2, rINST, lsr #8           @ r2<- AA
2949    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2950    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2952    GOTO_OPCODE(ip)                     @ jump to next instruction
2953
2954
2955/* ------------------------------ */
2956    .balign 64
2957.L_OP_SGET_CHAR: /* 0x65 */
2958/* File: armv5te/OP_SGET_CHAR.S */
2959/* File: armv5te/OP_SGET.S */
2960    /*
2961     * General 32-bit SGET handler.
2962     *
2963     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2964     */
2965    /* op vAA, field@BBBB */
2966    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2967    FETCH(r1, 1)                        @ r1<- field ref BBBB
2968    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2969    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2970    cmp     r0, #0                      @ is resolved entry null?
2971    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2972.LOP_SGET_CHAR_finish: @ field ptr in r0
2973    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2974    mov     r2, rINST, lsr #8           @ r2<- AA
2975    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2976    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2977    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2978    GOTO_OPCODE(ip)                     @ jump to next instruction
2979
2980
2981/* ------------------------------ */
2982    .balign 64
2983.L_OP_SGET_SHORT: /* 0x66 */
2984/* File: armv5te/OP_SGET_SHORT.S */
2985/* File: armv5te/OP_SGET.S */
2986    /*
2987     * General 32-bit SGET handler.
2988     *
2989     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2990     */
2991    /* op vAA, field@BBBB */
2992    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2993    FETCH(r1, 1)                        @ r1<- field ref BBBB
2994    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2995    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2996    cmp     r0, #0                      @ is resolved entry null?
2997    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2998.LOP_SGET_SHORT_finish: @ field ptr in r0
2999    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
3000    mov     r2, rINST, lsr #8           @ r2<- AA
3001    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3002    SET_VREG(r1, r2)                    @ fp[AA]<- r1
3003    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3004    GOTO_OPCODE(ip)                     @ jump to next instruction
3005
3006
3007/* ------------------------------ */
3008    .balign 64
3009.L_OP_SPUT: /* 0x67 */
3010/* File: armv5te/OP_SPUT.S */
3011    /*
3012     * General 32-bit SPUT handler.
3013     *
3014     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3015     */
3016    /* op vAA, field@BBBB */
3017    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3018    FETCH(r1, 1)                        @ r1<- field ref BBBB
3019    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3020    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3021    cmp     r0, #0                      @ is resolved entry null?
3022    beq     .LOP_SPUT_resolve         @ yes, do resolve
3023.LOP_SPUT_finish:   @ field ptr in r0
3024    mov     r2, rINST, lsr #8           @ r2<- AA
3025    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3026    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3028    str     r1, [r0, #offStaticField_value] @ field<- vAA
3029    GOTO_OPCODE(ip)                     @ jump to next instruction
3030
3031/* ------------------------------ */
3032    .balign 64
3033.L_OP_SPUT_WIDE: /* 0x68 */
3034/* File: armv5te/OP_SPUT_WIDE.S */
3035    /*
3036     * 64-bit SPUT handler.
3037     */
3038    /* sput-wide vAA, field@BBBB */
3039    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3040    FETCH(r1, 1)                        @ r1<- field ref BBBB
3041    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3042    mov     r9, rINST, lsr #8           @ r9<- AA
3043    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3044    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3045    cmp     r2, #0                      @ is resolved entry null?
3046    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3047.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3049    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3050    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3051    .if 0
3052    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3053    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
3054    .else
3055    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3056    .endif
3057    GOTO_OPCODE(r10)                    @ jump to next instruction
3058
3059/* ------------------------------ */
3060    .balign 64
3061.L_OP_SPUT_OBJECT: /* 0x69 */
3062/* File: armv5te/OP_SPUT_OBJECT.S */
3063/* File: armv5te/OP_SPUT.S */
3064    /*
3065     * General 32-bit SPUT handler.
3066     *
3067     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3068     */
3069    /* op vAA, field@BBBB */
3070    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3071    FETCH(r1, 1)                        @ r1<- field ref BBBB
3072    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3073    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3074    cmp     r0, #0                      @ is resolved entry null?
3075    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3076.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3077    mov     r2, rINST, lsr #8           @ r2<- AA
3078    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3079    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3080    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3081    str     r1, [r0, #offStaticField_value] @ field<- vAA
3082    GOTO_OPCODE(ip)                     @ jump to next instruction
3083
3084
3085/* ------------------------------ */
3086    .balign 64
3087.L_OP_SPUT_BOOLEAN: /* 0x6a */
3088/* File: armv5te/OP_SPUT_BOOLEAN.S */
3089/* File: armv5te/OP_SPUT.S */
3090    /*
3091     * General 32-bit SPUT handler.
3092     *
3093     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3094     */
3095    /* op vAA, field@BBBB */
3096    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3097    FETCH(r1, 1)                        @ r1<- field ref BBBB
3098    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3099    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3100    cmp     r0, #0                      @ is resolved entry null?
3101    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3102.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3103    mov     r2, rINST, lsr #8           @ r2<- AA
3104    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3105    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3106    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3107    str     r1, [r0, #offStaticField_value] @ field<- vAA
3108    GOTO_OPCODE(ip)                     @ jump to next instruction
3109
3110
3111/* ------------------------------ */
3112    .balign 64
3113.L_OP_SPUT_BYTE: /* 0x6b */
3114/* File: armv5te/OP_SPUT_BYTE.S */
3115/* File: armv5te/OP_SPUT.S */
3116    /*
3117     * General 32-bit SPUT handler.
3118     *
3119     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3120     */
3121    /* op vAA, field@BBBB */
3122    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3123    FETCH(r1, 1)                        @ r1<- field ref BBBB
3124    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3125    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3126    cmp     r0, #0                      @ is resolved entry null?
3127    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3128.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3129    mov     r2, rINST, lsr #8           @ r2<- AA
3130    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3131    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3132    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
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_CHAR: /* 0x6c */
3140/* File: armv5te/OP_SPUT_CHAR.S */
3141/* File: armv5te/OP_SPUT.S */
3142    /*
3143     * General 32-bit SPUT handler.
3144     *
3145     * for: sput, sput-object, 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_CHAR_resolve         @ yes, do resolve
3154.LOP_SPUT_CHAR_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    str     r1, [r0, #offStaticField_value] @ field<- vAA
3160    GOTO_OPCODE(ip)                     @ jump to next instruction
3161
3162
3163/* ------------------------------ */
3164    .balign 64
3165.L_OP_SPUT_SHORT: /* 0x6d */
3166/* File: armv5te/OP_SPUT_SHORT.S */
3167/* File: armv5te/OP_SPUT.S */
3168    /*
3169     * General 32-bit SPUT handler.
3170     *
3171     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3172     */
3173    /* op vAA, field@BBBB */
3174    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3175    FETCH(r1, 1)                        @ r1<- field ref BBBB
3176    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3177    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3178    cmp     r0, #0                      @ is resolved entry null?
3179    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3180.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3181    mov     r2, rINST, lsr #8           @ r2<- AA
3182    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3183    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3185    str     r1, [r0, #offStaticField_value] @ field<- vAA
3186    GOTO_OPCODE(ip)                     @ jump to next instruction
3187
3188
3189/* ------------------------------ */
3190    .balign 64
3191.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3192/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3193    /*
3194     * Handle a virtual method call.
3195     *
3196     * for: invoke-virtual, invoke-virtual/range
3197     */
3198    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3199    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3200    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3201    FETCH(r1, 1)                        @ r1<- BBBB
3202    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3203    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3204    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3205    .if     (!0)
3206    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3207    .endif
3208    cmp     r0, #0                      @ already resolved?
3209    EXPORT_PC()                         @ must export for invoke
3210    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3211    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3212    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3213    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3214    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3215    cmp     r0, #0                      @ got null?
3216    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3217    b       common_exceptionThrown      @ yes, handle exception
3218
3219/* ------------------------------ */
3220    .balign 64
3221.L_OP_INVOKE_SUPER: /* 0x6f */
3222/* File: armv5te/OP_INVOKE_SUPER.S */
3223    /*
3224     * Handle a "super" method call.
3225     *
3226     * for: invoke-super, invoke-super/range
3227     */
3228    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3229    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3230    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3231    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3232    .if     (!0)
3233    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3234    .endif
3235    FETCH(r1, 1)                        @ r1<- BBBB
3236    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3237    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3238    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3239    cmp     r2, #0                      @ null "this"?
3240    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3241    beq     common_errNullObject        @ null "this", throw exception
3242    cmp     r0, #0                      @ already resolved?
3243    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3244    EXPORT_PC()                         @ must export for invoke
3245    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3246    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3247
3248/* ------------------------------ */
3249    .balign 64
3250.L_OP_INVOKE_DIRECT: /* 0x70 */
3251/* File: armv5te/OP_INVOKE_DIRECT.S */
3252    /*
3253     * Handle a direct method call.
3254     *
3255     * (We could defer the "is 'this' pointer null" test to the common
3256     * method invocation code, and use a flag to indicate that static
3257     * calls don't count.  If we do this as part of copying the arguments
3258     * out we could avoiding loading the first arg twice.)
3259     *
3260     * for: invoke-direct, invoke-direct/range
3261     */
3262    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3263    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3264    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3265    FETCH(r1, 1)                        @ r1<- BBBB
3266    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3267    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3268    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3269    .if     (!0)
3270    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3271    .endif
3272    cmp     r0, #0                      @ already resolved?
3273    EXPORT_PC()                         @ must export for invoke
3274    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3275    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3276.LOP_INVOKE_DIRECT_finish:
3277    cmp     r2, #0                      @ null "this" ref?
3278    bne     common_invokeMethodNoRange   @ no, continue on
3279    b       common_errNullObject        @ yes, throw exception
3280
3281/* ------------------------------ */
3282    .balign 64
3283.L_OP_INVOKE_STATIC: /* 0x71 */
3284/* File: armv5te/OP_INVOKE_STATIC.S */
3285    /*
3286     * Handle a static method call.
3287     *
3288     * for: invoke-static, invoke-static/range
3289     */
3290    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3291    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3292    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3293    FETCH(r1, 1)                        @ r1<- BBBB
3294    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3295    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3296    cmp     r0, #0                      @ already resolved?
3297    EXPORT_PC()                         @ must export for invoke
3298    bne     common_invokeMethodNoRange @ yes, continue on
32990:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3300    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3301    mov     r2, #METHOD_STATIC          @ resolver method type
3302    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3303    cmp     r0, #0                      @ got null?
3304    bne     common_invokeMethodNoRange @ no, continue
3305    b       common_exceptionThrown      @ yes, handle exception
3306
3307
3308/* ------------------------------ */
3309    .balign 64
3310.L_OP_INVOKE_INTERFACE: /* 0x72 */
3311/* File: armv5te/OP_INVOKE_INTERFACE.S */
3312    /*
3313     * Handle an interface method call.
3314     *
3315     * for: invoke-interface, invoke-interface/range
3316     */
3317    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3318    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3319    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3320    FETCH(r1, 1)                        @ r1<- BBBB
3321    .if     (!0)
3322    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3323    .endif
3324    EXPORT_PC()                         @ must export for invoke
3325    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3326    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3327    cmp     r0, #0                      @ null obj?
3328    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3329    beq     common_errNullObject        @ yes, fail
3330    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3331    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3332    cmp     r0, #0                      @ failed?
3333    beq     common_exceptionThrown      @ yes, handle exception
3334    b       common_invokeMethodNoRange @ jump to common handler
3335
3336
3337/* ------------------------------ */
3338    .balign 64
3339.L_OP_UNUSED_73: /* 0x73 */
3340/* File: armv5te/OP_UNUSED_73.S */
3341/* File: armv5te/unused.S */
3342    bl      common_abort
3343
3344
3345
3346/* ------------------------------ */
3347    .balign 64
3348.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3349/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3350/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3351    /*
3352     * Handle a virtual method call.
3353     *
3354     * for: invoke-virtual, invoke-virtual/range
3355     */
3356    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3357    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3358    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3359    FETCH(r1, 1)                        @ r1<- BBBB
3360    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3361    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3362    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3363    .if     (!1)
3364    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3365    .endif
3366    cmp     r0, #0                      @ already resolved?
3367    EXPORT_PC()                         @ must export for invoke
3368    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3369    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3370    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3371    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3372    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3373    cmp     r0, #0                      @ got null?
3374    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3375    b       common_exceptionThrown      @ yes, handle exception
3376
3377
3378/* ------------------------------ */
3379    .balign 64
3380.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3381/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3382/* File: armv5te/OP_INVOKE_SUPER.S */
3383    /*
3384     * Handle a "super" method call.
3385     *
3386     * for: invoke-super, invoke-super/range
3387     */
3388    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3389    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3390    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3391    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3392    .if     (!1)
3393    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3394    .endif
3395    FETCH(r1, 1)                        @ r1<- BBBB
3396    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3397    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3398    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3399    cmp     r2, #0                      @ null "this"?
3400    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3401    beq     common_errNullObject        @ null "this", throw exception
3402    cmp     r0, #0                      @ already resolved?
3403    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3404    EXPORT_PC()                         @ must export for invoke
3405    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3406    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3407
3408
3409/* ------------------------------ */
3410    .balign 64
3411.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3412/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3413/* File: armv5te/OP_INVOKE_DIRECT.S */
3414    /*
3415     * Handle a direct method call.
3416     *
3417     * (We could defer the "is 'this' pointer null" test to the common
3418     * method invocation code, and use a flag to indicate that static
3419     * calls don't count.  If we do this as part of copying the arguments
3420     * out we could avoiding loading the first arg twice.)
3421     *
3422     * for: invoke-direct, invoke-direct/range
3423     */
3424    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3425    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3426    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3427    FETCH(r1, 1)                        @ r1<- BBBB
3428    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3429    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3430    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3431    .if     (!1)
3432    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3433    .endif
3434    cmp     r0, #0                      @ already resolved?
3435    EXPORT_PC()                         @ must export for invoke
3436    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3437    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3438.LOP_INVOKE_DIRECT_RANGE_finish:
3439    cmp     r2, #0                      @ null "this" ref?
3440    bne     common_invokeMethodRange   @ no, continue on
3441    b       common_errNullObject        @ yes, throw exception
3442
3443
3444/* ------------------------------ */
3445    .balign 64
3446.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3447/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3448/* File: armv5te/OP_INVOKE_STATIC.S */
3449    /*
3450     * Handle a static method call.
3451     *
3452     * for: invoke-static, invoke-static/range
3453     */
3454    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3455    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3456    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3457    FETCH(r1, 1)                        @ r1<- BBBB
3458    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3459    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3460    cmp     r0, #0                      @ already resolved?
3461    EXPORT_PC()                         @ must export for invoke
3462    bne     common_invokeMethodRange @ yes, continue on
34630:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3464    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3465    mov     r2, #METHOD_STATIC          @ resolver method type
3466    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3467    cmp     r0, #0                      @ got null?
3468    bne     common_invokeMethodRange @ no, continue
3469    b       common_exceptionThrown      @ yes, handle exception
3470
3471
3472
3473/* ------------------------------ */
3474    .balign 64
3475.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3476/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3477/* File: armv5te/OP_INVOKE_INTERFACE.S */
3478    /*
3479     * Handle an interface method call.
3480     *
3481     * for: invoke-interface, invoke-interface/range
3482     */
3483    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3484    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3485    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3486    FETCH(r1, 1)                        @ r1<- BBBB
3487    .if     (!1)
3488    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3489    .endif
3490    EXPORT_PC()                         @ must export for invoke
3491    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3492    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3493    cmp     r0, #0                      @ null obj?
3494    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3495    beq     common_errNullObject        @ yes, fail
3496    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3497    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3498    cmp     r0, #0                      @ failed?
3499    beq     common_exceptionThrown      @ yes, handle exception
3500    b       common_invokeMethodRange @ jump to common handler
3501
3502
3503
3504/* ------------------------------ */
3505    .balign 64
3506.L_OP_UNUSED_79: /* 0x79 */
3507/* File: armv5te/OP_UNUSED_79.S */
3508/* File: armv5te/unused.S */
3509    bl      common_abort
3510
3511
3512
3513/* ------------------------------ */
3514    .balign 64
3515.L_OP_UNUSED_7A: /* 0x7a */
3516/* File: armv5te/OP_UNUSED_7A.S */
3517/* File: armv5te/unused.S */
3518    bl      common_abort
3519
3520
3521
3522/* ------------------------------ */
3523    .balign 64
3524.L_OP_NEG_INT: /* 0x7b */
3525/* File: armv6t2/OP_NEG_INT.S */
3526/* File: armv6t2/unop.S */
3527    /*
3528     * Generic 32-bit unary operation.  Provide an "instr" line that
3529     * specifies an instruction that performs "result = op r0".
3530     * This could be an ARM instruction or a function call.
3531     *
3532     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3533     *      int-to-byte, int-to-char, int-to-short
3534     */
3535    /* unop vA, vB */
3536    mov     r3, rINST, lsr #12          @ r3<- B
3537    ubfx    r9, rINST, #8, #4           @ r9<- A
3538    GET_VREG(r0, r3)                    @ r0<- vB
3539                               @ optional op; may set condition codes
3540    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3541    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3542    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3543    SET_VREG(r0, r9)                    @ vAA<- r0
3544    GOTO_OPCODE(ip)                     @ jump to next instruction
3545    /* 8-9 instructions */
3546
3547
3548/* ------------------------------ */
3549    .balign 64
3550.L_OP_NOT_INT: /* 0x7c */
3551/* File: armv6t2/OP_NOT_INT.S */
3552/* File: armv6t2/unop.S */
3553    /*
3554     * Generic 32-bit unary operation.  Provide an "instr" line that
3555     * specifies an instruction that performs "result = op r0".
3556     * This could be an ARM instruction or a function call.
3557     *
3558     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3559     *      int-to-byte, int-to-char, int-to-short
3560     */
3561    /* unop vA, vB */
3562    mov     r3, rINST, lsr #12          @ r3<- B
3563    ubfx    r9, rINST, #8, #4           @ r9<- A
3564    GET_VREG(r0, r3)                    @ r0<- vB
3565                               @ optional op; may set condition codes
3566    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3567    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3568    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3569    SET_VREG(r0, r9)                    @ vAA<- r0
3570    GOTO_OPCODE(ip)                     @ jump to next instruction
3571    /* 8-9 instructions */
3572
3573
3574/* ------------------------------ */
3575    .balign 64
3576.L_OP_NEG_LONG: /* 0x7d */
3577/* File: armv6t2/OP_NEG_LONG.S */
3578/* File: armv6t2/unopWide.S */
3579    /*
3580     * Generic 64-bit unary operation.  Provide an "instr" line that
3581     * specifies an instruction that performs "result = op r0/r1".
3582     * This could be an ARM instruction or a function call.
3583     *
3584     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3585     */
3586    /* unop vA, vB */
3587    mov     r3, rINST, lsr #12          @ r3<- B
3588    ubfx    r9, rINST, #8, #4           @ r9<- A
3589    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3590    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3591    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3593    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3594    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3596    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3597    GOTO_OPCODE(ip)                     @ jump to next instruction
3598    /* 10-11 instructions */
3599
3600
3601
3602/* ------------------------------ */
3603    .balign 64
3604.L_OP_NOT_LONG: /* 0x7e */
3605/* File: armv6t2/OP_NOT_LONG.S */
3606/* File: armv6t2/unopWide.S */
3607    /*
3608     * Generic 64-bit unary operation.  Provide an "instr" line that
3609     * specifies an instruction that performs "result = op r0/r1".
3610     * This could be an ARM instruction or a function call.
3611     *
3612     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3613     */
3614    /* unop vA, vB */
3615    mov     r3, rINST, lsr #12          @ r3<- B
3616    ubfx    r9, rINST, #8, #4           @ r9<- A
3617    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3618    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3619    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3620    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3621    mvn     r0, r0                           @ optional op; may set condition codes
3622    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3623    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3624    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3625    GOTO_OPCODE(ip)                     @ jump to next instruction
3626    /* 10-11 instructions */
3627
3628
3629
3630/* ------------------------------ */
3631    .balign 64
3632.L_OP_NEG_FLOAT: /* 0x7f */
3633/* File: armv6t2/OP_NEG_FLOAT.S */
3634/* File: armv6t2/unop.S */
3635    /*
3636     * Generic 32-bit unary operation.  Provide an "instr" line that
3637     * specifies an instruction that performs "result = op r0".
3638     * This could be an ARM instruction or a function call.
3639     *
3640     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3641     *      int-to-byte, int-to-char, int-to-short
3642     */
3643    /* unop vA, vB */
3644    mov     r3, rINST, lsr #12          @ r3<- B
3645    ubfx    r9, rINST, #8, #4           @ r9<- A
3646    GET_VREG(r0, r3)                    @ r0<- vB
3647                               @ optional op; may set condition codes
3648    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3649    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3650    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3651    SET_VREG(r0, r9)                    @ vAA<- r0
3652    GOTO_OPCODE(ip)                     @ jump to next instruction
3653    /* 8-9 instructions */
3654
3655
3656/* ------------------------------ */
3657    .balign 64
3658.L_OP_NEG_DOUBLE: /* 0x80 */
3659/* File: armv6t2/OP_NEG_DOUBLE.S */
3660/* File: armv6t2/unopWide.S */
3661    /*
3662     * Generic 64-bit unary operation.  Provide an "instr" line that
3663     * specifies an instruction that performs "result = op r0/r1".
3664     * This could be an ARM instruction or a function call.
3665     *
3666     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3667     */
3668    /* unop vA, vB */
3669    mov     r3, rINST, lsr #12          @ r3<- B
3670    ubfx    r9, rINST, #8, #4           @ r9<- A
3671    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3672    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3673    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3674    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3675                               @ optional op; may set condition codes
3676    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3677    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3678    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3679    GOTO_OPCODE(ip)                     @ jump to next instruction
3680    /* 10-11 instructions */
3681
3682
3683
3684/* ------------------------------ */
3685    .balign 64
3686.L_OP_INT_TO_LONG: /* 0x81 */
3687/* File: armv6t2/OP_INT_TO_LONG.S */
3688/* File: armv6t2/unopWider.S */
3689    /*
3690     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3691     * that specifies an instruction that performs "result = op r0", where
3692     * "result" is a 64-bit quantity in r0/r1.
3693     *
3694     * For: int-to-long, int-to-double, float-to-long, float-to-double
3695     */
3696    /* unop vA, vB */
3697    mov     r3, rINST, lsr #12          @ r3<- B
3698    ubfx    r9, rINST, #8, #4           @ r9<- A
3699    GET_VREG(r0, r3)                    @ r0<- vB
3700    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3701                               @ optional op; may set condition codes
3702    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3703    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3704    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3705    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3706    GOTO_OPCODE(ip)                     @ jump to next instruction
3707    /* 9-10 instructions */
3708
3709
3710/* ------------------------------ */
3711    .balign 64
3712.L_OP_INT_TO_FLOAT: /* 0x82 */
3713/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3714/* File: arm-vfp/funop.S */
3715    /*
3716     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3717     * line that specifies an instruction that performs "s1 = op s0".
3718     *
3719     * for: int-to-float, float-to-int
3720     */
3721    /* unop vA, vB */
3722    mov     r3, rINST, lsr #12          @ r3<- B
3723    mov     r9, rINST, lsr #8           @ r9<- A+
3724    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3725    flds    s0, [r3]                    @ s0<- vB
3726    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3727    and     r9, r9, #15                 @ r9<- A
3728    fsitos  s1, s0                              @ s1<- op
3729    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3730    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3731    fsts    s1, [r9]                    @ vA<- s1
3732    GOTO_OPCODE(ip)                     @ jump to next instruction
3733
3734
3735/* ------------------------------ */
3736    .balign 64
3737.L_OP_INT_TO_DOUBLE: /* 0x83 */
3738/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3739/* File: arm-vfp/funopWider.S */
3740    /*
3741     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3742     * "instr" line that specifies an instruction that performs "d0 = op s0".
3743     *
3744     * For: int-to-double, float-to-double
3745     */
3746    /* unop vA, vB */
3747    mov     r3, rINST, lsr #12          @ r3<- B
3748    mov     r9, rINST, lsr #8           @ r9<- A+
3749    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3750    flds    s0, [r3]                    @ s0<- vB
3751    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3752    and     r9, r9, #15                 @ r9<- A
3753    fsitod  d0, s0                              @ d0<- op
3754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3755    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3756    fstd    d0, [r9]                    @ vA<- d0
3757    GOTO_OPCODE(ip)                     @ jump to next instruction
3758
3759
3760/* ------------------------------ */
3761    .balign 64
3762.L_OP_LONG_TO_INT: /* 0x84 */
3763/* File: armv5te/OP_LONG_TO_INT.S */
3764/* we ignore the high word, making this equivalent to a 32-bit reg move */
3765/* File: armv5te/OP_MOVE.S */
3766    /* for move, move-object, long-to-int */
3767    /* op vA, vB */
3768    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3769    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3770    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3771    GET_VREG(r2, r1)                    @ r2<- fp[B]
3772    and     r0, r0, #15
3773    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3774    SET_VREG(r2, r0)                    @ fp[A]<- r2
3775    GOTO_OPCODE(ip)                     @ execute next instruction
3776
3777
3778
3779/* ------------------------------ */
3780    .balign 64
3781.L_OP_LONG_TO_FLOAT: /* 0x85 */
3782/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3783/* File: armv6t2/unopNarrower.S */
3784    /*
3785     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3786     * that specifies an instruction that performs "result = op r0/r1", where
3787     * "result" is a 32-bit quantity in r0.
3788     *
3789     * For: long-to-float, double-to-int, double-to-float
3790     *
3791     * (This would work for long-to-int, but that instruction is actually
3792     * an exact match for OP_MOVE.)
3793     */
3794    /* unop vA, vB */
3795    mov     r3, rINST, lsr #12          @ r3<- B
3796    ubfx    r9, rINST, #8, #4           @ r9<- A
3797    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3798    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3799    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3800                               @ optional op; may set condition codes
3801    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3803    SET_VREG(r0, r9)                    @ vA<- r0
3804    GOTO_OPCODE(ip)                     @ jump to next instruction
3805    /* 9-10 instructions */
3806
3807
3808/* ------------------------------ */
3809    .balign 64
3810.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3811/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3812/* File: armv6t2/unopWide.S */
3813    /*
3814     * Generic 64-bit unary operation.  Provide an "instr" line that
3815     * specifies an instruction that performs "result = op r0/r1".
3816     * This could be an ARM instruction or a function call.
3817     *
3818     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3819     */
3820    /* unop vA, vB */
3821    mov     r3, rINST, lsr #12          @ r3<- B
3822    ubfx    r9, rINST, #8, #4           @ r9<- A
3823    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3824    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3825    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3826    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3827                               @ optional op; may set condition codes
3828    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3830    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3831    GOTO_OPCODE(ip)                     @ jump to next instruction
3832    /* 10-11 instructions */
3833
3834
3835
3836/* ------------------------------ */
3837    .balign 64
3838.L_OP_FLOAT_TO_INT: /* 0x87 */
3839/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3840/* File: arm-vfp/funop.S */
3841    /*
3842     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3843     * line that specifies an instruction that performs "s1 = op s0".
3844     *
3845     * for: int-to-float, float-to-int
3846     */
3847    /* unop vA, vB */
3848    mov     r3, rINST, lsr #12          @ r3<- B
3849    mov     r9, rINST, lsr #8           @ r9<- A+
3850    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3851    flds    s0, [r3]                    @ s0<- vB
3852    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3853    and     r9, r9, #15                 @ r9<- A
3854    ftosizs s1, s0                              @ s1<- op
3855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3856    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3857    fsts    s1, [r9]                    @ vA<- s1
3858    GOTO_OPCODE(ip)                     @ jump to next instruction
3859
3860
3861/* ------------------------------ */
3862    .balign 64
3863.L_OP_FLOAT_TO_LONG: /* 0x88 */
3864/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3865@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3866/* File: armv6t2/unopWider.S */
3867    /*
3868     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3869     * that specifies an instruction that performs "result = op r0", where
3870     * "result" is a 64-bit quantity in r0/r1.
3871     *
3872     * For: int-to-long, int-to-double, float-to-long, float-to-double
3873     */
3874    /* unop vA, vB */
3875    mov     r3, rINST, lsr #12          @ r3<- B
3876    ubfx    r9, rINST, #8, #4           @ r9<- A
3877    GET_VREG(r0, r3)                    @ r0<- vB
3878    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3879                               @ optional op; may set condition codes
3880    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3881    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3882    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3883    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3884    GOTO_OPCODE(ip)                     @ jump to next instruction
3885    /* 9-10 instructions */
3886
3887
3888
3889/* ------------------------------ */
3890    .balign 64
3891.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3892/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3893/* File: arm-vfp/funopWider.S */
3894    /*
3895     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3896     * "instr" line that specifies an instruction that performs "d0 = op s0".
3897     *
3898     * For: int-to-double, float-to-double
3899     */
3900    /* unop vA, vB */
3901    mov     r3, rINST, lsr #12          @ r3<- B
3902    mov     r9, rINST, lsr #8           @ r9<- A+
3903    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3904    flds    s0, [r3]                    @ s0<- vB
3905    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3906    and     r9, r9, #15                 @ r9<- A
3907    fcvtds  d0, s0                              @ d0<- op
3908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3909    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3910    fstd    d0, [r9]                    @ vA<- d0
3911    GOTO_OPCODE(ip)                     @ jump to next instruction
3912
3913
3914/* ------------------------------ */
3915    .balign 64
3916.L_OP_DOUBLE_TO_INT: /* 0x8a */
3917/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3918/* File: arm-vfp/funopNarrower.S */
3919    /*
3920     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3921     * "instr" line that specifies an instruction that performs "s0 = op d0".
3922     *
3923     * For: double-to-int, double-to-float
3924     */
3925    /* unop vA, vB */
3926    mov     r3, rINST, lsr #12          @ r3<- B
3927    mov     r9, rINST, lsr #8           @ r9<- A+
3928    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3929    fldd    d0, [r3]                    @ d0<- vB
3930    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3931    and     r9, r9, #15                 @ r9<- A
3932    ftosizd  s0, d0                              @ s0<- op
3933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3934    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3935    fsts    s0, [r9]                    @ vA<- s0
3936    GOTO_OPCODE(ip)                     @ jump to next instruction
3937
3938
3939/* ------------------------------ */
3940    .balign 64
3941.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3942/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3943@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3944/* File: armv6t2/unopWide.S */
3945    /*
3946     * Generic 64-bit unary operation.  Provide an "instr" line that
3947     * specifies an instruction that performs "result = op r0/r1".
3948     * This could be an ARM instruction or a function call.
3949     *
3950     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3951     */
3952    /* unop vA, vB */
3953    mov     r3, rINST, lsr #12          @ r3<- B
3954    ubfx    r9, rINST, #8, #4           @ r9<- A
3955    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3956    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3957    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3958    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3959                               @ optional op; may set condition codes
3960    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3962    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3963    GOTO_OPCODE(ip)                     @ jump to next instruction
3964    /* 10-11 instructions */
3965
3966
3967
3968
3969/* ------------------------------ */
3970    .balign 64
3971.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3972/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3973/* File: arm-vfp/funopNarrower.S */
3974    /*
3975     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3976     * "instr" line that specifies an instruction that performs "s0 = op d0".
3977     *
3978     * For: double-to-int, double-to-float
3979     */
3980    /* unop vA, vB */
3981    mov     r3, rINST, lsr #12          @ r3<- B
3982    mov     r9, rINST, lsr #8           @ r9<- A+
3983    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3984    fldd    d0, [r3]                    @ d0<- vB
3985    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3986    and     r9, r9, #15                 @ r9<- A
3987    fcvtsd  s0, d0                              @ s0<- op
3988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3989    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3990    fsts    s0, [r9]                    @ vA<- s0
3991    GOTO_OPCODE(ip)                     @ jump to next instruction
3992
3993
3994/* ------------------------------ */
3995    .balign 64
3996.L_OP_INT_TO_BYTE: /* 0x8d */
3997/* File: armv6t2/OP_INT_TO_BYTE.S */
3998/* File: armv6t2/unop.S */
3999    /*
4000     * Generic 32-bit unary operation.  Provide an "instr" line that
4001     * specifies an instruction that performs "result = op r0".
4002     * This could be an ARM instruction or a function call.
4003     *
4004     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005     *      int-to-byte, int-to-char, int-to-short
4006     */
4007    /* unop vA, vB */
4008    mov     r3, rINST, lsr #12          @ r3<- B
4009    ubfx    r9, rINST, #8, #4           @ r9<- A
4010    GET_VREG(r0, r3)                    @ r0<- vB
4011                               @ optional op; may set condition codes
4012    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4013    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
4014    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4015    SET_VREG(r0, r9)                    @ vAA<- r0
4016    GOTO_OPCODE(ip)                     @ jump to next instruction
4017    /* 8-9 instructions */
4018
4019
4020/* ------------------------------ */
4021    .balign 64
4022.L_OP_INT_TO_CHAR: /* 0x8e */
4023/* File: armv6t2/OP_INT_TO_CHAR.S */
4024/* File: armv6t2/unop.S */
4025    /*
4026     * Generic 32-bit unary operation.  Provide an "instr" line that
4027     * specifies an instruction that performs "result = op r0".
4028     * This could be an ARM instruction or a function call.
4029     *
4030     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4031     *      int-to-byte, int-to-char, int-to-short
4032     */
4033    /* unop vA, vB */
4034    mov     r3, rINST, lsr #12          @ r3<- B
4035    ubfx    r9, rINST, #8, #4           @ r9<- A
4036    GET_VREG(r0, r3)                    @ r0<- vB
4037                               @ optional op; may set condition codes
4038    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4039    uxth    r0, r0                              @ r0<- op, r0-r3 changed
4040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4041    SET_VREG(r0, r9)                    @ vAA<- r0
4042    GOTO_OPCODE(ip)                     @ jump to next instruction
4043    /* 8-9 instructions */
4044
4045
4046/* ------------------------------ */
4047    .balign 64
4048.L_OP_INT_TO_SHORT: /* 0x8f */
4049/* File: armv6t2/OP_INT_TO_SHORT.S */
4050/* File: armv6t2/unop.S */
4051    /*
4052     * Generic 32-bit unary operation.  Provide an "instr" line that
4053     * specifies an instruction that performs "result = op r0".
4054     * This could be an ARM instruction or a function call.
4055     *
4056     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4057     *      int-to-byte, int-to-char, int-to-short
4058     */
4059    /* unop vA, vB */
4060    mov     r3, rINST, lsr #12          @ r3<- B
4061    ubfx    r9, rINST, #8, #4           @ r9<- A
4062    GET_VREG(r0, r3)                    @ r0<- vB
4063                               @ optional op; may set condition codes
4064    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4065    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4066    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4067    SET_VREG(r0, r9)                    @ vAA<- r0
4068    GOTO_OPCODE(ip)                     @ jump to next instruction
4069    /* 8-9 instructions */
4070
4071
4072/* ------------------------------ */
4073    .balign 64
4074.L_OP_ADD_INT: /* 0x90 */
4075/* File: armv5te/OP_ADD_INT.S */
4076/* File: armv5te/binop.S */
4077    /*
4078     * Generic 32-bit binary operation.  Provide an "instr" line that
4079     * specifies an instruction that performs "result = r0 op r1".
4080     * This could be an ARM instruction or a function call.  (If the result
4081     * comes back in a register other than r0, you can override "result".)
4082     *
4083     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4084     * vCC (r1).  Useful for integer division and modulus.  Note that we
4085     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4086     * handles it correctly.
4087     *
4088     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4089     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4090     *      mul-float, div-float, rem-float
4091     */
4092    /* binop vAA, vBB, vCC */
4093    FETCH(r0, 1)                        @ r0<- CCBB
4094    mov     r9, rINST, lsr #8           @ r9<- AA
4095    mov     r3, r0, lsr #8              @ r3<- CC
4096    and     r2, r0, #255                @ r2<- BB
4097    GET_VREG(r1, r3)                    @ r1<- vCC
4098    GET_VREG(r0, r2)                    @ r0<- vBB
4099    .if 0
4100    cmp     r1, #0                      @ is second operand zero?
4101    beq     common_errDivideByZero
4102    .endif
4103
4104    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4105                               @ optional op; may set condition codes
4106    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4107    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4108    SET_VREG(r0, r9)               @ vAA<- r0
4109    GOTO_OPCODE(ip)                     @ jump to next instruction
4110    /* 11-14 instructions */
4111
4112
4113
4114/* ------------------------------ */
4115    .balign 64
4116.L_OP_SUB_INT: /* 0x91 */
4117/* File: armv5te/OP_SUB_INT.S */
4118/* File: armv5te/binop.S */
4119    /*
4120     * Generic 32-bit binary operation.  Provide an "instr" line that
4121     * specifies an instruction that performs "result = r0 op r1".
4122     * This could be an ARM instruction or a function call.  (If the result
4123     * comes back in a register other than r0, you can override "result".)
4124     *
4125     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4126     * vCC (r1).  Useful for integer division and modulus.  Note that we
4127     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4128     * handles it correctly.
4129     *
4130     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4131     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4132     *      mul-float, div-float, rem-float
4133     */
4134    /* binop vAA, vBB, vCC */
4135    FETCH(r0, 1)                        @ r0<- CCBB
4136    mov     r9, rINST, lsr #8           @ r9<- AA
4137    mov     r3, r0, lsr #8              @ r3<- CC
4138    and     r2, r0, #255                @ r2<- BB
4139    GET_VREG(r1, r3)                    @ r1<- vCC
4140    GET_VREG(r0, r2)                    @ r0<- vBB
4141    .if 0
4142    cmp     r1, #0                      @ is second operand zero?
4143    beq     common_errDivideByZero
4144    .endif
4145
4146    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4147                               @ optional op; may set condition codes
4148    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4149    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4150    SET_VREG(r0, r9)               @ vAA<- r0
4151    GOTO_OPCODE(ip)                     @ jump to next instruction
4152    /* 11-14 instructions */
4153
4154
4155
4156/* ------------------------------ */
4157    .balign 64
4158.L_OP_MUL_INT: /* 0x92 */
4159/* File: armv5te/OP_MUL_INT.S */
4160/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4161/* File: armv5te/binop.S */
4162    /*
4163     * Generic 32-bit binary operation.  Provide an "instr" line that
4164     * specifies an instruction that performs "result = r0 op r1".
4165     * This could be an ARM instruction or a function call.  (If the result
4166     * comes back in a register other than r0, you can override "result".)
4167     *
4168     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4169     * vCC (r1).  Useful for integer division and modulus.  Note that we
4170     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4171     * handles it correctly.
4172     *
4173     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4174     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4175     *      mul-float, div-float, rem-float
4176     */
4177    /* binop vAA, vBB, vCC */
4178    FETCH(r0, 1)                        @ r0<- CCBB
4179    mov     r9, rINST, lsr #8           @ r9<- AA
4180    mov     r3, r0, lsr #8              @ r3<- CC
4181    and     r2, r0, #255                @ r2<- BB
4182    GET_VREG(r1, r3)                    @ r1<- vCC
4183    GET_VREG(r0, r2)                    @ r0<- vBB
4184    .if 0
4185    cmp     r1, #0                      @ is second operand zero?
4186    beq     common_errDivideByZero
4187    .endif
4188
4189    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4190                               @ optional op; may set condition codes
4191    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4192    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4193    SET_VREG(r0, r9)               @ vAA<- r0
4194    GOTO_OPCODE(ip)                     @ jump to next instruction
4195    /* 11-14 instructions */
4196
4197
4198
4199/* ------------------------------ */
4200    .balign 64
4201.L_OP_DIV_INT: /* 0x93 */
4202/* File: armv5te/OP_DIV_INT.S */
4203/* File: armv5te/binop.S */
4204    /*
4205     * Generic 32-bit binary operation.  Provide an "instr" line that
4206     * specifies an instruction that performs "result = r0 op r1".
4207     * This could be an ARM instruction or a function call.  (If the result
4208     * comes back in a register other than r0, you can override "result".)
4209     *
4210     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4211     * vCC (r1).  Useful for integer division and modulus.  Note that we
4212     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4213     * handles it correctly.
4214     *
4215     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4216     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4217     *      mul-float, div-float, rem-float
4218     */
4219    /* binop vAA, vBB, vCC */
4220    FETCH(r0, 1)                        @ r0<- CCBB
4221    mov     r9, rINST, lsr #8           @ r9<- AA
4222    mov     r3, r0, lsr #8              @ r3<- CC
4223    and     r2, r0, #255                @ r2<- BB
4224    GET_VREG(r1, r3)                    @ r1<- vCC
4225    GET_VREG(r0, r2)                    @ r0<- vBB
4226    .if 1
4227    cmp     r1, #0                      @ is second operand zero?
4228    beq     common_errDivideByZero
4229    .endif
4230
4231    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4232                               @ optional op; may set condition codes
4233    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4234    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4235    SET_VREG(r0, r9)               @ vAA<- r0
4236    GOTO_OPCODE(ip)                     @ jump to next instruction
4237    /* 11-14 instructions */
4238
4239
4240
4241/* ------------------------------ */
4242    .balign 64
4243.L_OP_REM_INT: /* 0x94 */
4244/* File: armv5te/OP_REM_INT.S */
4245/* idivmod returns quotient in r0 and remainder in r1 */
4246/* File: armv5te/binop.S */
4247    /*
4248     * Generic 32-bit binary operation.  Provide an "instr" line that
4249     * specifies an instruction that performs "result = r0 op r1".
4250     * This could be an ARM instruction or a function call.  (If the result
4251     * comes back in a register other than r0, you can override "result".)
4252     *
4253     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4254     * vCC (r1).  Useful for integer division and modulus.  Note that we
4255     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4256     * handles it correctly.
4257     *
4258     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4259     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4260     *      mul-float, div-float, rem-float
4261     */
4262    /* binop vAA, vBB, vCC */
4263    FETCH(r0, 1)                        @ r0<- CCBB
4264    mov     r9, rINST, lsr #8           @ r9<- AA
4265    mov     r3, r0, lsr #8              @ r3<- CC
4266    and     r2, r0, #255                @ r2<- BB
4267    GET_VREG(r1, r3)                    @ r1<- vCC
4268    GET_VREG(r0, r2)                    @ r0<- vBB
4269    .if 1
4270    cmp     r1, #0                      @ is second operand zero?
4271    beq     common_errDivideByZero
4272    .endif
4273
4274    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4275                               @ optional op; may set condition codes
4276    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4277    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4278    SET_VREG(r1, r9)               @ vAA<- r1
4279    GOTO_OPCODE(ip)                     @ jump to next instruction
4280    /* 11-14 instructions */
4281
4282
4283
4284/* ------------------------------ */
4285    .balign 64
4286.L_OP_AND_INT: /* 0x95 */
4287/* File: armv5te/OP_AND_INT.S */
4288/* File: armv5te/binop.S */
4289    /*
4290     * Generic 32-bit binary operation.  Provide an "instr" line that
4291     * specifies an instruction that performs "result = r0 op r1".
4292     * This could be an ARM instruction or a function call.  (If the result
4293     * comes back in a register other than r0, you can override "result".)
4294     *
4295     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4296     * vCC (r1).  Useful for integer division and modulus.  Note that we
4297     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4298     * handles it correctly.
4299     *
4300     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4301     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4302     *      mul-float, div-float, rem-float
4303     */
4304    /* binop vAA, vBB, vCC */
4305    FETCH(r0, 1)                        @ r0<- CCBB
4306    mov     r9, rINST, lsr #8           @ r9<- AA
4307    mov     r3, r0, lsr #8              @ r3<- CC
4308    and     r2, r0, #255                @ r2<- BB
4309    GET_VREG(r1, r3)                    @ r1<- vCC
4310    GET_VREG(r0, r2)                    @ r0<- vBB
4311    .if 0
4312    cmp     r1, #0                      @ is second operand zero?
4313    beq     common_errDivideByZero
4314    .endif
4315
4316    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4317                               @ optional op; may set condition codes
4318    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4319    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4320    SET_VREG(r0, r9)               @ vAA<- r0
4321    GOTO_OPCODE(ip)                     @ jump to next instruction
4322    /* 11-14 instructions */
4323
4324
4325
4326/* ------------------------------ */
4327    .balign 64
4328.L_OP_OR_INT: /* 0x96 */
4329/* File: armv5te/OP_OR_INT.S */
4330/* File: armv5te/binop.S */
4331    /*
4332     * Generic 32-bit binary operation.  Provide an "instr" line that
4333     * specifies an instruction that performs "result = r0 op r1".
4334     * This could be an ARM instruction or a function call.  (If the result
4335     * comes back in a register other than r0, you can override "result".)
4336     *
4337     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4338     * vCC (r1).  Useful for integer division and modulus.  Note that we
4339     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4340     * handles it correctly.
4341     *
4342     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4343     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4344     *      mul-float, div-float, rem-float
4345     */
4346    /* binop vAA, vBB, vCC */
4347    FETCH(r0, 1)                        @ r0<- CCBB
4348    mov     r9, rINST, lsr #8           @ r9<- AA
4349    mov     r3, r0, lsr #8              @ r3<- CC
4350    and     r2, r0, #255                @ r2<- BB
4351    GET_VREG(r1, r3)                    @ r1<- vCC
4352    GET_VREG(r0, r2)                    @ r0<- vBB
4353    .if 0
4354    cmp     r1, #0                      @ is second operand zero?
4355    beq     common_errDivideByZero
4356    .endif
4357
4358    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4359                               @ optional op; may set condition codes
4360    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4361    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4362    SET_VREG(r0, r9)               @ vAA<- r0
4363    GOTO_OPCODE(ip)                     @ jump to next instruction
4364    /* 11-14 instructions */
4365
4366
4367
4368/* ------------------------------ */
4369    .balign 64
4370.L_OP_XOR_INT: /* 0x97 */
4371/* File: armv5te/OP_XOR_INT.S */
4372/* File: armv5te/binop.S */
4373    /*
4374     * Generic 32-bit binary operation.  Provide an "instr" line that
4375     * specifies an instruction that performs "result = r0 op r1".
4376     * This could be an ARM instruction or a function call.  (If the result
4377     * comes back in a register other than r0, you can override "result".)
4378     *
4379     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4380     * vCC (r1).  Useful for integer division and modulus.  Note that we
4381     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4382     * handles it correctly.
4383     *
4384     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4385     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4386     *      mul-float, div-float, rem-float
4387     */
4388    /* binop vAA, vBB, vCC */
4389    FETCH(r0, 1)                        @ r0<- CCBB
4390    mov     r9, rINST, lsr #8           @ r9<- AA
4391    mov     r3, r0, lsr #8              @ r3<- CC
4392    and     r2, r0, #255                @ r2<- BB
4393    GET_VREG(r1, r3)                    @ r1<- vCC
4394    GET_VREG(r0, r2)                    @ r0<- vBB
4395    .if 0
4396    cmp     r1, #0                      @ is second operand zero?
4397    beq     common_errDivideByZero
4398    .endif
4399
4400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4401                               @ optional op; may set condition codes
4402    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4403    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4404    SET_VREG(r0, r9)               @ vAA<- r0
4405    GOTO_OPCODE(ip)                     @ jump to next instruction
4406    /* 11-14 instructions */
4407
4408
4409
4410/* ------------------------------ */
4411    .balign 64
4412.L_OP_SHL_INT: /* 0x98 */
4413/* File: armv5te/OP_SHL_INT.S */
4414/* File: armv5te/binop.S */
4415    /*
4416     * Generic 32-bit binary operation.  Provide an "instr" line that
4417     * specifies an instruction that performs "result = r0 op r1".
4418     * This could be an ARM instruction or a function call.  (If the result
4419     * comes back in a register other than r0, you can override "result".)
4420     *
4421     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4422     * vCC (r1).  Useful for integer division and modulus.  Note that we
4423     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4424     * handles it correctly.
4425     *
4426     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4427     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4428     *      mul-float, div-float, rem-float
4429     */
4430    /* binop vAA, vBB, vCC */
4431    FETCH(r0, 1)                        @ r0<- CCBB
4432    mov     r9, rINST, lsr #8           @ r9<- AA
4433    mov     r3, r0, lsr #8              @ r3<- CC
4434    and     r2, r0, #255                @ r2<- BB
4435    GET_VREG(r1, r3)                    @ r1<- vCC
4436    GET_VREG(r0, r2)                    @ r0<- vBB
4437    .if 0
4438    cmp     r1, #0                      @ is second operand zero?
4439    beq     common_errDivideByZero
4440    .endif
4441
4442    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4443    and     r1, r1, #31                           @ optional op; may set condition codes
4444    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4445    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4446    SET_VREG(r0, r9)               @ vAA<- r0
4447    GOTO_OPCODE(ip)                     @ jump to next instruction
4448    /* 11-14 instructions */
4449
4450
4451
4452/* ------------------------------ */
4453    .balign 64
4454.L_OP_SHR_INT: /* 0x99 */
4455/* File: armv5te/OP_SHR_INT.S */
4456/* File: armv5te/binop.S */
4457    /*
4458     * Generic 32-bit binary operation.  Provide an "instr" line that
4459     * specifies an instruction that performs "result = r0 op r1".
4460     * This could be an ARM instruction or a function call.  (If the result
4461     * comes back in a register other than r0, you can override "result".)
4462     *
4463     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4464     * vCC (r1).  Useful for integer division and modulus.  Note that we
4465     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4466     * handles it correctly.
4467     *
4468     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4469     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4470     *      mul-float, div-float, rem-float
4471     */
4472    /* binop vAA, vBB, vCC */
4473    FETCH(r0, 1)                        @ r0<- CCBB
4474    mov     r9, rINST, lsr #8           @ r9<- AA
4475    mov     r3, r0, lsr #8              @ r3<- CC
4476    and     r2, r0, #255                @ r2<- BB
4477    GET_VREG(r1, r3)                    @ r1<- vCC
4478    GET_VREG(r0, r2)                    @ r0<- vBB
4479    .if 0
4480    cmp     r1, #0                      @ is second operand zero?
4481    beq     common_errDivideByZero
4482    .endif
4483
4484    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4485    and     r1, r1, #31                           @ optional op; may set condition codes
4486    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4488    SET_VREG(r0, r9)               @ vAA<- r0
4489    GOTO_OPCODE(ip)                     @ jump to next instruction
4490    /* 11-14 instructions */
4491
4492
4493
4494/* ------------------------------ */
4495    .balign 64
4496.L_OP_USHR_INT: /* 0x9a */
4497/* File: armv5te/OP_USHR_INT.S */
4498/* File: armv5te/binop.S */
4499    /*
4500     * Generic 32-bit binary operation.  Provide an "instr" line that
4501     * specifies an instruction that performs "result = r0 op r1".
4502     * This could be an ARM instruction or a function call.  (If the result
4503     * comes back in a register other than r0, you can override "result".)
4504     *
4505     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4506     * vCC (r1).  Useful for integer division and modulus.  Note that we
4507     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4508     * handles it correctly.
4509     *
4510     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4511     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4512     *      mul-float, div-float, rem-float
4513     */
4514    /* binop vAA, vBB, vCC */
4515    FETCH(r0, 1)                        @ r0<- CCBB
4516    mov     r9, rINST, lsr #8           @ r9<- AA
4517    mov     r3, r0, lsr #8              @ r3<- CC
4518    and     r2, r0, #255                @ r2<- BB
4519    GET_VREG(r1, r3)                    @ r1<- vCC
4520    GET_VREG(r0, r2)                    @ r0<- vBB
4521    .if 0
4522    cmp     r1, #0                      @ is second operand zero?
4523    beq     common_errDivideByZero
4524    .endif
4525
4526    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4527    and     r1, r1, #31                           @ optional op; may set condition codes
4528    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4529    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4530    SET_VREG(r0, r9)               @ vAA<- r0
4531    GOTO_OPCODE(ip)                     @ jump to next instruction
4532    /* 11-14 instructions */
4533
4534
4535
4536/* ------------------------------ */
4537    .balign 64
4538.L_OP_ADD_LONG: /* 0x9b */
4539/* File: armv5te/OP_ADD_LONG.S */
4540/* File: armv5te/binopWide.S */
4541    /*
4542     * Generic 64-bit binary operation.  Provide an "instr" line that
4543     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4544     * This could be an ARM instruction or a function call.  (If the result
4545     * comes back in a register other than r0, you can override "result".)
4546     *
4547     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4548     * vCC (r1).  Useful for integer division and modulus.
4549     *
4550     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4551     *      xor-long, add-double, sub-double, mul-double, div-double,
4552     *      rem-double
4553     *
4554     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4555     */
4556    /* binop vAA, vBB, vCC */
4557    FETCH(r0, 1)                        @ r0<- CCBB
4558    mov     r9, rINST, lsr #8           @ r9<- AA
4559    and     r2, r0, #255                @ r2<- BB
4560    mov     r3, r0, lsr #8              @ r3<- CC
4561    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4562    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4563    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4564    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4565    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4566    .if 0
4567    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4568    beq     common_errDivideByZero
4569    .endif
4570    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4571
4572    adds    r0, r0, r2                           @ optional op; may set condition codes
4573    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4574    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4575    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4576    GOTO_OPCODE(ip)                     @ jump to next instruction
4577    /* 14-17 instructions */
4578
4579
4580
4581/* ------------------------------ */
4582    .balign 64
4583.L_OP_SUB_LONG: /* 0x9c */
4584/* File: armv5te/OP_SUB_LONG.S */
4585/* File: armv5te/binopWide.S */
4586    /*
4587     * Generic 64-bit binary operation.  Provide an "instr" line that
4588     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4589     * This could be an ARM instruction or a function call.  (If the result
4590     * comes back in a register other than r0, you can override "result".)
4591     *
4592     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4593     * vCC (r1).  Useful for integer division and modulus.
4594     *
4595     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4596     *      xor-long, add-double, sub-double, mul-double, div-double,
4597     *      rem-double
4598     *
4599     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4600     */
4601    /* binop vAA, vBB, vCC */
4602    FETCH(r0, 1)                        @ r0<- CCBB
4603    mov     r9, rINST, lsr #8           @ r9<- AA
4604    and     r2, r0, #255                @ r2<- BB
4605    mov     r3, r0, lsr #8              @ r3<- CC
4606    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4607    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4608    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4609    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4610    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4611    .if 0
4612    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4613    beq     common_errDivideByZero
4614    .endif
4615    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4616
4617    subs    r0, r0, r2                           @ optional op; may set condition codes
4618    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4620    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4621    GOTO_OPCODE(ip)                     @ jump to next instruction
4622    /* 14-17 instructions */
4623
4624
4625
4626/* ------------------------------ */
4627    .balign 64
4628.L_OP_MUL_LONG: /* 0x9d */
4629/* File: armv5te/OP_MUL_LONG.S */
4630    /*
4631     * Signed 64-bit integer multiply.
4632     *
4633     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4634     *        WX
4635     *      x YZ
4636     *  --------
4637     *     ZW ZX
4638     *  YW YX
4639     *
4640     * The low word of the result holds ZX, the high word holds
4641     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4642     * it doesn't fit in the low 64 bits.
4643     *
4644     * Unlike most ARM math operations, multiply instructions have
4645     * restrictions on using the same register more than once (Rd and Rm
4646     * cannot be the same).
4647     */
4648    /* mul-long vAA, vBB, vCC */
4649    FETCH(r0, 1)                        @ r0<- CCBB
4650    and     r2, r0, #255                @ r2<- BB
4651    mov     r3, r0, lsr #8              @ r3<- CC
4652    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4653    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4654    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4655    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4656    mul     ip, r2, r1                  @  ip<- ZxW
4657    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4658    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4659    mov     r0, rINST, lsr #8           @ r0<- AA
4660    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4661    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4662    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4663    b       .LOP_MUL_LONG_finish
4664
4665/* ------------------------------ */
4666    .balign 64
4667.L_OP_DIV_LONG: /* 0x9e */
4668/* File: armv5te/OP_DIV_LONG.S */
4669/* File: armv5te/binopWide.S */
4670    /*
4671     * Generic 64-bit binary operation.  Provide an "instr" line that
4672     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4673     * This could be an ARM instruction or a function call.  (If the result
4674     * comes back in a register other than r0, you can override "result".)
4675     *
4676     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4677     * vCC (r1).  Useful for integer division and modulus.
4678     *
4679     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4680     *      xor-long, add-double, sub-double, mul-double, div-double,
4681     *      rem-double
4682     *
4683     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4684     */
4685    /* binop vAA, vBB, vCC */
4686    FETCH(r0, 1)                        @ r0<- CCBB
4687    mov     r9, rINST, lsr #8           @ r9<- AA
4688    and     r2, r0, #255                @ r2<- BB
4689    mov     r3, r0, lsr #8              @ r3<- CC
4690    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4691    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4692    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4693    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4694    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4695    .if 1
4696    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4697    beq     common_errDivideByZero
4698    .endif
4699    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4700
4701                               @ optional op; may set condition codes
4702    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4703    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4704    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4705    GOTO_OPCODE(ip)                     @ jump to next instruction
4706    /* 14-17 instructions */
4707
4708
4709
4710/* ------------------------------ */
4711    .balign 64
4712.L_OP_REM_LONG: /* 0x9f */
4713/* File: armv5te/OP_REM_LONG.S */
4714/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4715/* File: armv5te/binopWide.S */
4716    /*
4717     * Generic 64-bit binary operation.  Provide an "instr" line that
4718     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4719     * This could be an ARM instruction or a function call.  (If the result
4720     * comes back in a register other than r0, you can override "result".)
4721     *
4722     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4723     * vCC (r1).  Useful for integer division and modulus.
4724     *
4725     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4726     *      xor-long, add-double, sub-double, mul-double, div-double,
4727     *      rem-double
4728     *
4729     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4730     */
4731    /* binop vAA, vBB, vCC */
4732    FETCH(r0, 1)                        @ r0<- CCBB
4733    mov     r9, rINST, lsr #8           @ r9<- AA
4734    and     r2, r0, #255                @ r2<- BB
4735    mov     r3, r0, lsr #8              @ r3<- CC
4736    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4737    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4738    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4739    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4740    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4741    .if 1
4742    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4743    beq     common_errDivideByZero
4744    .endif
4745    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4746
4747                               @ optional op; may set condition codes
4748    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4749    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4750    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4751    GOTO_OPCODE(ip)                     @ jump to next instruction
4752    /* 14-17 instructions */
4753
4754
4755
4756/* ------------------------------ */
4757    .balign 64
4758.L_OP_AND_LONG: /* 0xa0 */
4759/* File: armv5te/OP_AND_LONG.S */
4760/* File: armv5te/binopWide.S */
4761    /*
4762     * Generic 64-bit binary operation.  Provide an "instr" line that
4763     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4764     * This could be an ARM instruction or a function call.  (If the result
4765     * comes back in a register other than r0, you can override "result".)
4766     *
4767     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4768     * vCC (r1).  Useful for integer division and modulus.
4769     *
4770     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4771     *      xor-long, add-double, sub-double, mul-double, div-double,
4772     *      rem-double
4773     *
4774     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4775     */
4776    /* binop vAA, vBB, vCC */
4777    FETCH(r0, 1)                        @ r0<- CCBB
4778    mov     r9, rINST, lsr #8           @ r9<- AA
4779    and     r2, r0, #255                @ r2<- BB
4780    mov     r3, r0, lsr #8              @ r3<- CC
4781    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4782    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4783    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4784    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4785    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4786    .if 0
4787    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4788    beq     common_errDivideByZero
4789    .endif
4790    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4791
4792    and     r0, r0, r2                           @ optional op; may set condition codes
4793    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4795    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4796    GOTO_OPCODE(ip)                     @ jump to next instruction
4797    /* 14-17 instructions */
4798
4799
4800
4801/* ------------------------------ */
4802    .balign 64
4803.L_OP_OR_LONG: /* 0xa1 */
4804/* File: armv5te/OP_OR_LONG.S */
4805/* File: armv5te/binopWide.S */
4806    /*
4807     * Generic 64-bit binary operation.  Provide an "instr" line that
4808     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4809     * This could be an ARM instruction or a function call.  (If the result
4810     * comes back in a register other than r0, you can override "result".)
4811     *
4812     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4813     * vCC (r1).  Useful for integer division and modulus.
4814     *
4815     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4816     *      xor-long, add-double, sub-double, mul-double, div-double,
4817     *      rem-double
4818     *
4819     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4820     */
4821    /* binop vAA, vBB, vCC */
4822    FETCH(r0, 1)                        @ r0<- CCBB
4823    mov     r9, rINST, lsr #8           @ r9<- AA
4824    and     r2, r0, #255                @ r2<- BB
4825    mov     r3, r0, lsr #8              @ r3<- CC
4826    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4827    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4828    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4829    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4830    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4831    .if 0
4832    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4833    beq     common_errDivideByZero
4834    .endif
4835    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4836
4837    orr     r0, r0, r2                           @ optional op; may set condition codes
4838    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4840    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4841    GOTO_OPCODE(ip)                     @ jump to next instruction
4842    /* 14-17 instructions */
4843
4844
4845
4846/* ------------------------------ */
4847    .balign 64
4848.L_OP_XOR_LONG: /* 0xa2 */
4849/* File: armv5te/OP_XOR_LONG.S */
4850/* File: armv5te/binopWide.S */
4851    /*
4852     * Generic 64-bit binary operation.  Provide an "instr" line that
4853     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4854     * This could be an ARM instruction or a function call.  (If the result
4855     * comes back in a register other than r0, you can override "result".)
4856     *
4857     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4858     * vCC (r1).  Useful for integer division and modulus.
4859     *
4860     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4861     *      xor-long, add-double, sub-double, mul-double, div-double,
4862     *      rem-double
4863     *
4864     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4865     */
4866    /* binop vAA, vBB, vCC */
4867    FETCH(r0, 1)                        @ r0<- CCBB
4868    mov     r9, rINST, lsr #8           @ r9<- AA
4869    and     r2, r0, #255                @ r2<- BB
4870    mov     r3, r0, lsr #8              @ r3<- CC
4871    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4872    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4873    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4874    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4875    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4876    .if 0
4877    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4878    beq     common_errDivideByZero
4879    .endif
4880    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4881
4882    eor     r0, r0, r2                           @ optional op; may set condition codes
4883    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4885    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4886    GOTO_OPCODE(ip)                     @ jump to next instruction
4887    /* 14-17 instructions */
4888
4889
4890
4891/* ------------------------------ */
4892    .balign 64
4893.L_OP_SHL_LONG: /* 0xa3 */
4894/* File: armv5te/OP_SHL_LONG.S */
4895    /*
4896     * Long integer shift.  This is different from the generic 32/64-bit
4897     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4898     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4899     * 6 bits of the shift distance.
4900     */
4901    /* shl-long vAA, vBB, vCC */
4902    FETCH(r0, 1)                        @ r0<- CCBB
4903    mov     r9, rINST, lsr #8           @ r9<- AA
4904    and     r3, r0, #255                @ r3<- BB
4905    mov     r0, r0, lsr #8              @ r0<- CC
4906    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4907    GET_VREG(r2, r0)                    @ r2<- vCC
4908    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4909    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4910    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4911
4912    mov     r1, r1, asl r2              @  r1<- r1 << r2
4913    rsb     r3, r2, #32                 @  r3<- 32 - r2
4914    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4915    subs    ip, r2, #32                 @  ip<- r2 - 32
4916    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4917    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4918    b       .LOP_SHL_LONG_finish
4919
4920/* ------------------------------ */
4921    .balign 64
4922.L_OP_SHR_LONG: /* 0xa4 */
4923/* File: armv5te/OP_SHR_LONG.S */
4924    /*
4925     * Long integer shift.  This is different from the generic 32/64-bit
4926     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4927     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4928     * 6 bits of the shift distance.
4929     */
4930    /* shr-long vAA, vBB, vCC */
4931    FETCH(r0, 1)                        @ r0<- CCBB
4932    mov     r9, rINST, lsr #8           @ r9<- AA
4933    and     r3, r0, #255                @ r3<- BB
4934    mov     r0, r0, lsr #8              @ r0<- CC
4935    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4936    GET_VREG(r2, r0)                    @ r2<- vCC
4937    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4938    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4939    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4940
4941    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4942    rsb     r3, r2, #32                 @  r3<- 32 - r2
4943    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4944    subs    ip, r2, #32                 @  ip<- r2 - 32
4945    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4946    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4947    b       .LOP_SHR_LONG_finish
4948
4949/* ------------------------------ */
4950    .balign 64
4951.L_OP_USHR_LONG: /* 0xa5 */
4952/* File: armv5te/OP_USHR_LONG.S */
4953    /*
4954     * Long integer shift.  This is different from the generic 32/64-bit
4955     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4956     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4957     * 6 bits of the shift distance.
4958     */
4959    /* ushr-long vAA, vBB, vCC */
4960    FETCH(r0, 1)                        @ r0<- CCBB
4961    mov     r9, rINST, lsr #8           @ r9<- AA
4962    and     r3, r0, #255                @ r3<- BB
4963    mov     r0, r0, lsr #8              @ r0<- CC
4964    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4965    GET_VREG(r2, r0)                    @ r2<- vCC
4966    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4967    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4968    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4969
4970    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4971    rsb     r3, r2, #32                 @  r3<- 32 - r2
4972    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4973    subs    ip, r2, #32                 @  ip<- r2 - 32
4974    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4975    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4976    b       .LOP_USHR_LONG_finish
4977
4978/* ------------------------------ */
4979    .balign 64
4980.L_OP_ADD_FLOAT: /* 0xa6 */
4981/* File: arm-vfp/OP_ADD_FLOAT.S */
4982/* File: arm-vfp/fbinop.S */
4983    /*
4984     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4985     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4986     * use the "softfp" ABI, this must be an instruction, not a function call.
4987     *
4988     * For: add-float, sub-float, mul-float, div-float
4989     */
4990    /* floatop vAA, vBB, vCC */
4991    FETCH(r0, 1)                        @ r0<- CCBB
4992    mov     r9, rINST, lsr #8           @ r9<- AA
4993    mov     r3, r0, lsr #8              @ r3<- CC
4994    and     r2, r0, #255                @ r2<- BB
4995    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4996    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4997    flds    s1, [r3]                    @ s1<- vCC
4998    flds    s0, [r2]                    @ s0<- vBB
4999
5000    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5001    fadds   s2, s0, s1                              @ s2<- op
5002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5003    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5004    fsts    s2, [r9]                    @ vAA<- s2
5005    GOTO_OPCODE(ip)                     @ jump to next instruction
5006
5007
5008/* ------------------------------ */
5009    .balign 64
5010.L_OP_SUB_FLOAT: /* 0xa7 */
5011/* File: arm-vfp/OP_SUB_FLOAT.S */
5012/* File: arm-vfp/fbinop.S */
5013    /*
5014     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5015     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5016     * use the "softfp" ABI, this must be an instruction, not a function call.
5017     *
5018     * For: add-float, sub-float, mul-float, div-float
5019     */
5020    /* floatop vAA, vBB, vCC */
5021    FETCH(r0, 1)                        @ r0<- CCBB
5022    mov     r9, rINST, lsr #8           @ r9<- AA
5023    mov     r3, r0, lsr #8              @ r3<- CC
5024    and     r2, r0, #255                @ r2<- BB
5025    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5026    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5027    flds    s1, [r3]                    @ s1<- vCC
5028    flds    s0, [r2]                    @ s0<- vBB
5029
5030    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5031    fsubs   s2, s0, s1                              @ s2<- op
5032    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5033    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5034    fsts    s2, [r9]                    @ vAA<- s2
5035    GOTO_OPCODE(ip)                     @ jump to next instruction
5036
5037
5038/* ------------------------------ */
5039    .balign 64
5040.L_OP_MUL_FLOAT: /* 0xa8 */
5041/* File: arm-vfp/OP_MUL_FLOAT.S */
5042/* File: arm-vfp/fbinop.S */
5043    /*
5044     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5045     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5046     * use the "softfp" ABI, this must be an instruction, not a function call.
5047     *
5048     * For: add-float, sub-float, mul-float, div-float
5049     */
5050    /* floatop vAA, vBB, vCC */
5051    FETCH(r0, 1)                        @ r0<- CCBB
5052    mov     r9, rINST, lsr #8           @ r9<- AA
5053    mov     r3, r0, lsr #8              @ r3<- CC
5054    and     r2, r0, #255                @ r2<- BB
5055    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5056    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5057    flds    s1, [r3]                    @ s1<- vCC
5058    flds    s0, [r2]                    @ s0<- vBB
5059
5060    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5061    fmuls   s2, s0, s1                              @ s2<- op
5062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5063    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5064    fsts    s2, [r9]                    @ vAA<- s2
5065    GOTO_OPCODE(ip)                     @ jump to next instruction
5066
5067
5068/* ------------------------------ */
5069    .balign 64
5070.L_OP_DIV_FLOAT: /* 0xa9 */
5071/* File: arm-vfp/OP_DIV_FLOAT.S */
5072/* File: arm-vfp/fbinop.S */
5073    /*
5074     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5075     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5076     * use the "softfp" ABI, this must be an instruction, not a function call.
5077     *
5078     * For: add-float, sub-float, mul-float, div-float
5079     */
5080    /* floatop vAA, vBB, vCC */
5081    FETCH(r0, 1)                        @ r0<- CCBB
5082    mov     r9, rINST, lsr #8           @ r9<- AA
5083    mov     r3, r0, lsr #8              @ r3<- CC
5084    and     r2, r0, #255                @ r2<- BB
5085    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5086    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5087    flds    s1, [r3]                    @ s1<- vCC
5088    flds    s0, [r2]                    @ s0<- vBB
5089
5090    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5091    fdivs   s2, s0, s1                              @ s2<- op
5092    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5093    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5094    fsts    s2, [r9]                    @ vAA<- s2
5095    GOTO_OPCODE(ip)                     @ jump to next instruction
5096
5097
5098/* ------------------------------ */
5099    .balign 64
5100.L_OP_REM_FLOAT: /* 0xaa */
5101/* File: armv5te/OP_REM_FLOAT.S */
5102/* EABI doesn't define a float remainder function, but libm does */
5103/* File: armv5te/binop.S */
5104    /*
5105     * Generic 32-bit binary operation.  Provide an "instr" line that
5106     * specifies an instruction that performs "result = r0 op r1".
5107     * This could be an ARM instruction or a function call.  (If the result
5108     * comes back in a register other than r0, you can override "result".)
5109     *
5110     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5111     * vCC (r1).  Useful for integer division and modulus.  Note that we
5112     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5113     * handles it correctly.
5114     *
5115     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5116     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5117     *      mul-float, div-float, rem-float
5118     */
5119    /* binop vAA, vBB, vCC */
5120    FETCH(r0, 1)                        @ r0<- CCBB
5121    mov     r9, rINST, lsr #8           @ r9<- AA
5122    mov     r3, r0, lsr #8              @ r3<- CC
5123    and     r2, r0, #255                @ r2<- BB
5124    GET_VREG(r1, r3)                    @ r1<- vCC
5125    GET_VREG(r0, r2)                    @ r0<- vBB
5126    .if 0
5127    cmp     r1, #0                      @ is second operand zero?
5128    beq     common_errDivideByZero
5129    .endif
5130
5131    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5132                               @ optional op; may set condition codes
5133    bl      fmodf                              @ r0<- op, r0-r3 changed
5134    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5135    SET_VREG(r0, r9)               @ vAA<- r0
5136    GOTO_OPCODE(ip)                     @ jump to next instruction
5137    /* 11-14 instructions */
5138
5139
5140
5141/* ------------------------------ */
5142    .balign 64
5143.L_OP_ADD_DOUBLE: /* 0xab */
5144/* File: arm-vfp/OP_ADD_DOUBLE.S */
5145/* File: arm-vfp/fbinopWide.S */
5146    /*
5147     * Generic 64-bit double-precision floating point binary operation.
5148     * Provide an "instr" line that specifies an instruction that performs
5149     * "d2 = d0 op d1".
5150     *
5151     * for: add-double, sub-double, mul-double, div-double
5152     */
5153    /* doubleop vAA, vBB, vCC */
5154    FETCH(r0, 1)                        @ r0<- CCBB
5155    mov     r9, rINST, lsr #8           @ r9<- AA
5156    mov     r3, r0, lsr #8              @ r3<- CC
5157    and     r2, r0, #255                @ r2<- BB
5158    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5159    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5160    fldd    d1, [r3]                    @ d1<- vCC
5161    fldd    d0, [r2]                    @ d0<- vBB
5162
5163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5164    faddd   d2, d0, d1                              @ s2<- op
5165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5166    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5167    fstd    d2, [r9]                    @ vAA<- d2
5168    GOTO_OPCODE(ip)                     @ jump to next instruction
5169
5170
5171/* ------------------------------ */
5172    .balign 64
5173.L_OP_SUB_DOUBLE: /* 0xac */
5174/* File: arm-vfp/OP_SUB_DOUBLE.S */
5175/* File: arm-vfp/fbinopWide.S */
5176    /*
5177     * Generic 64-bit double-precision floating point binary operation.
5178     * Provide an "instr" line that specifies an instruction that performs
5179     * "d2 = d0 op d1".
5180     *
5181     * for: add-double, sub-double, mul-double, div-double
5182     */
5183    /* doubleop vAA, vBB, vCC */
5184    FETCH(r0, 1)                        @ r0<- CCBB
5185    mov     r9, rINST, lsr #8           @ r9<- AA
5186    mov     r3, r0, lsr #8              @ r3<- CC
5187    and     r2, r0, #255                @ r2<- BB
5188    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5189    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5190    fldd    d1, [r3]                    @ d1<- vCC
5191    fldd    d0, [r2]                    @ d0<- vBB
5192
5193    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5194    fsubd   d2, d0, d1                              @ s2<- op
5195    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5196    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5197    fstd    d2, [r9]                    @ vAA<- d2
5198    GOTO_OPCODE(ip)                     @ jump to next instruction
5199
5200
5201/* ------------------------------ */
5202    .balign 64
5203.L_OP_MUL_DOUBLE: /* 0xad */
5204/* File: arm-vfp/OP_MUL_DOUBLE.S */
5205/* File: arm-vfp/fbinopWide.S */
5206    /*
5207     * Generic 64-bit double-precision floating point binary operation.
5208     * Provide an "instr" line that specifies an instruction that performs
5209     * "d2 = d0 op d1".
5210     *
5211     * for: add-double, sub-double, mul-double, div-double
5212     */
5213    /* doubleop vAA, vBB, vCC */
5214    FETCH(r0, 1)                        @ r0<- CCBB
5215    mov     r9, rINST, lsr #8           @ r9<- AA
5216    mov     r3, r0, lsr #8              @ r3<- CC
5217    and     r2, r0, #255                @ r2<- BB
5218    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5219    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5220    fldd    d1, [r3]                    @ d1<- vCC
5221    fldd    d0, [r2]                    @ d0<- vBB
5222
5223    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5224    fmuld   d2, d0, d1                              @ s2<- op
5225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5226    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5227    fstd    d2, [r9]                    @ vAA<- d2
5228    GOTO_OPCODE(ip)                     @ jump to next instruction
5229
5230
5231/* ------------------------------ */
5232    .balign 64
5233.L_OP_DIV_DOUBLE: /* 0xae */
5234/* File: arm-vfp/OP_DIV_DOUBLE.S */
5235/* File: arm-vfp/fbinopWide.S */
5236    /*
5237     * Generic 64-bit double-precision floating point binary operation.
5238     * Provide an "instr" line that specifies an instruction that performs
5239     * "d2 = d0 op d1".
5240     *
5241     * for: add-double, sub-double, mul-double, div-double
5242     */
5243    /* doubleop vAA, vBB, vCC */
5244    FETCH(r0, 1)                        @ r0<- CCBB
5245    mov     r9, rINST, lsr #8           @ r9<- AA
5246    mov     r3, r0, lsr #8              @ r3<- CC
5247    and     r2, r0, #255                @ r2<- BB
5248    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5249    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5250    fldd    d1, [r3]                    @ d1<- vCC
5251    fldd    d0, [r2]                    @ d0<- vBB
5252
5253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5254    fdivd   d2, d0, d1                              @ s2<- op
5255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5256    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5257    fstd    d2, [r9]                    @ vAA<- d2
5258    GOTO_OPCODE(ip)                     @ jump to next instruction
5259
5260
5261/* ------------------------------ */
5262    .balign 64
5263.L_OP_REM_DOUBLE: /* 0xaf */
5264/* File: armv5te/OP_REM_DOUBLE.S */
5265/* EABI doesn't define a double remainder function, but libm does */
5266/* File: armv5te/binopWide.S */
5267    /*
5268     * Generic 64-bit binary operation.  Provide an "instr" line that
5269     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5270     * This could be an ARM instruction or a function call.  (If the result
5271     * comes back in a register other than r0, you can override "result".)
5272     *
5273     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5274     * vCC (r1).  Useful for integer division and modulus.
5275     *
5276     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5277     *      xor-long, add-double, sub-double, mul-double, div-double,
5278     *      rem-double
5279     *
5280     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5281     */
5282    /* binop vAA, vBB, vCC */
5283    FETCH(r0, 1)                        @ r0<- CCBB
5284    mov     r9, rINST, lsr #8           @ r9<- AA
5285    and     r2, r0, #255                @ r2<- BB
5286    mov     r3, r0, lsr #8              @ r3<- CC
5287    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5288    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5289    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5290    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5291    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5292    .if 0
5293    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5294    beq     common_errDivideByZero
5295    .endif
5296    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5297
5298                               @ optional op; may set condition codes
5299    bl      fmod                              @ result<- op, r0-r3 changed
5300    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5301    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5302    GOTO_OPCODE(ip)                     @ jump to next instruction
5303    /* 14-17 instructions */
5304
5305
5306
5307/* ------------------------------ */
5308    .balign 64
5309.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5310/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5311/* File: armv6t2/binop2addr.S */
5312    /*
5313     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5314     * that specifies an instruction that performs "result = r0 op r1".
5315     * This could be an ARM instruction or a function call.  (If the result
5316     * comes back in a register other than r0, you can override "result".)
5317     *
5318     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5319     * vCC (r1).  Useful for integer division and modulus.
5320     *
5321     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5322     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5323     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5324     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5325     */
5326    /* binop/2addr vA, vB */
5327    mov     r3, rINST, lsr #12          @ r3<- B
5328    ubfx    r9, rINST, #8, #4           @ r9<- A
5329    GET_VREG(r1, r3)                    @ r1<- vB
5330    GET_VREG(r0, r9)                    @ r0<- vA
5331    .if 0
5332    cmp     r1, #0                      @ is second operand zero?
5333    beq     common_errDivideByZero
5334    .endif
5335    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5336
5337                               @ optional op; may set condition codes
5338    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5340    SET_VREG(r0, r9)               @ vAA<- r0
5341    GOTO_OPCODE(ip)                     @ jump to next instruction
5342    /* 10-13 instructions */
5343
5344
5345
5346/* ------------------------------ */
5347    .balign 64
5348.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5349/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5350/* File: armv6t2/binop2addr.S */
5351    /*
5352     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5353     * that specifies an instruction that performs "result = r0 op r1".
5354     * This could be an ARM instruction or a function call.  (If the result
5355     * comes back in a register other than r0, you can override "result".)
5356     *
5357     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5358     * vCC (r1).  Useful for integer division and modulus.
5359     *
5360     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5361     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5362     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5363     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5364     */
5365    /* binop/2addr vA, vB */
5366    mov     r3, rINST, lsr #12          @ r3<- B
5367    ubfx    r9, rINST, #8, #4           @ r9<- A
5368    GET_VREG(r1, r3)                    @ r1<- vB
5369    GET_VREG(r0, r9)                    @ r0<- vA
5370    .if 0
5371    cmp     r1, #0                      @ is second operand zero?
5372    beq     common_errDivideByZero
5373    .endif
5374    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5375
5376                               @ optional op; may set condition codes
5377    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5379    SET_VREG(r0, r9)               @ vAA<- r0
5380    GOTO_OPCODE(ip)                     @ jump to next instruction
5381    /* 10-13 instructions */
5382
5383
5384
5385/* ------------------------------ */
5386    .balign 64
5387.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5388/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5389/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5390/* File: armv6t2/binop2addr.S */
5391    /*
5392     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5393     * that specifies an instruction that performs "result = r0 op r1".
5394     * This could be an ARM instruction or a function call.  (If the result
5395     * comes back in a register other than r0, you can override "result".)
5396     *
5397     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5398     * vCC (r1).  Useful for integer division and modulus.
5399     *
5400     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5401     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5402     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5403     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5404     */
5405    /* binop/2addr vA, vB */
5406    mov     r3, rINST, lsr #12          @ r3<- B
5407    ubfx    r9, rINST, #8, #4           @ r9<- A
5408    GET_VREG(r1, r3)                    @ r1<- vB
5409    GET_VREG(r0, r9)                    @ r0<- vA
5410    .if 0
5411    cmp     r1, #0                      @ is second operand zero?
5412    beq     common_errDivideByZero
5413    .endif
5414    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5415
5416                               @ optional op; may set condition codes
5417    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5418    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5419    SET_VREG(r0, r9)               @ vAA<- r0
5420    GOTO_OPCODE(ip)                     @ jump to next instruction
5421    /* 10-13 instructions */
5422
5423
5424
5425/* ------------------------------ */
5426    .balign 64
5427.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5428/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5429/* File: armv6t2/binop2addr.S */
5430    /*
5431     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5432     * that specifies an instruction that performs "result = r0 op r1".
5433     * This could be an ARM instruction or a function call.  (If the result
5434     * comes back in a register other than r0, you can override "result".)
5435     *
5436     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5437     * vCC (r1).  Useful for integer division and modulus.
5438     *
5439     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5440     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5441     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5442     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5443     */
5444    /* binop/2addr vA, vB */
5445    mov     r3, rINST, lsr #12          @ r3<- B
5446    ubfx    r9, rINST, #8, #4           @ r9<- A
5447    GET_VREG(r1, r3)                    @ r1<- vB
5448    GET_VREG(r0, r9)                    @ r0<- vA
5449    .if 1
5450    cmp     r1, #0                      @ is second operand zero?
5451    beq     common_errDivideByZero
5452    .endif
5453    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5454
5455                               @ optional op; may set condition codes
5456    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5458    SET_VREG(r0, r9)               @ vAA<- r0
5459    GOTO_OPCODE(ip)                     @ jump to next instruction
5460    /* 10-13 instructions */
5461
5462
5463
5464/* ------------------------------ */
5465    .balign 64
5466.L_OP_REM_INT_2ADDR: /* 0xb4 */
5467/* File: armv6t2/OP_REM_INT_2ADDR.S */
5468/* idivmod returns quotient in r0 and remainder in r1 */
5469/* File: armv6t2/binop2addr.S */
5470    /*
5471     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5472     * that specifies an instruction that performs "result = r0 op r1".
5473     * This could be an ARM instruction or a function call.  (If the result
5474     * comes back in a register other than r0, you can override "result".)
5475     *
5476     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5477     * vCC (r1).  Useful for integer division and modulus.
5478     *
5479     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5480     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5481     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5482     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5483     */
5484    /* binop/2addr vA, vB */
5485    mov     r3, rINST, lsr #12          @ r3<- B
5486    ubfx    r9, rINST, #8, #4           @ r9<- A
5487    GET_VREG(r1, r3)                    @ r1<- vB
5488    GET_VREG(r0, r9)                    @ r0<- vA
5489    .if 1
5490    cmp     r1, #0                      @ is second operand zero?
5491    beq     common_errDivideByZero
5492    .endif
5493    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5494
5495                               @ optional op; may set condition codes
5496    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5497    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5498    SET_VREG(r1, r9)               @ vAA<- r1
5499    GOTO_OPCODE(ip)                     @ jump to next instruction
5500    /* 10-13 instructions */
5501
5502
5503
5504/* ------------------------------ */
5505    .balign 64
5506.L_OP_AND_INT_2ADDR: /* 0xb5 */
5507/* File: armv6t2/OP_AND_INT_2ADDR.S */
5508/* File: armv6t2/binop2addr.S */
5509    /*
5510     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5511     * that specifies an instruction that performs "result = r0 op r1".
5512     * This could be an ARM instruction or a function call.  (If the result
5513     * comes back in a register other than r0, you can override "result".)
5514     *
5515     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5516     * vCC (r1).  Useful for integer division and modulus.
5517     *
5518     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5519     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5520     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5521     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5522     */
5523    /* binop/2addr vA, vB */
5524    mov     r3, rINST, lsr #12          @ r3<- B
5525    ubfx    r9, rINST, #8, #4           @ r9<- A
5526    GET_VREG(r1, r3)                    @ r1<- vB
5527    GET_VREG(r0, r9)                    @ r0<- vA
5528    .if 0
5529    cmp     r1, #0                      @ is second operand zero?
5530    beq     common_errDivideByZero
5531    .endif
5532    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5533
5534                               @ optional op; may set condition codes
5535    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5537    SET_VREG(r0, r9)               @ vAA<- r0
5538    GOTO_OPCODE(ip)                     @ jump to next instruction
5539    /* 10-13 instructions */
5540
5541
5542
5543/* ------------------------------ */
5544    .balign 64
5545.L_OP_OR_INT_2ADDR: /* 0xb6 */
5546/* File: armv6t2/OP_OR_INT_2ADDR.S */
5547/* File: armv6t2/binop2addr.S */
5548    /*
5549     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5550     * that specifies an instruction that performs "result = r0 op r1".
5551     * This could be an ARM instruction or a function call.  (If the result
5552     * comes back in a register other than r0, you can override "result".)
5553     *
5554     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5555     * vCC (r1).  Useful for integer division and modulus.
5556     *
5557     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5558     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5559     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5560     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5561     */
5562    /* binop/2addr vA, vB */
5563    mov     r3, rINST, lsr #12          @ r3<- B
5564    ubfx    r9, rINST, #8, #4           @ r9<- A
5565    GET_VREG(r1, r3)                    @ r1<- vB
5566    GET_VREG(r0, r9)                    @ r0<- vA
5567    .if 0
5568    cmp     r1, #0                      @ is second operand zero?
5569    beq     common_errDivideByZero
5570    .endif
5571    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5572
5573                               @ optional op; may set condition codes
5574    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5575    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5576    SET_VREG(r0, r9)               @ vAA<- r0
5577    GOTO_OPCODE(ip)                     @ jump to next instruction
5578    /* 10-13 instructions */
5579
5580
5581
5582/* ------------------------------ */
5583    .balign 64
5584.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5585/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5586/* File: armv6t2/binop2addr.S */
5587    /*
5588     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5589     * that specifies an instruction that performs "result = r0 op r1".
5590     * This could be an ARM instruction or a function call.  (If the result
5591     * comes back in a register other than r0, you can override "result".)
5592     *
5593     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5594     * vCC (r1).  Useful for integer division and modulus.
5595     *
5596     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5597     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5598     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5599     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5600     */
5601    /* binop/2addr vA, vB */
5602    mov     r3, rINST, lsr #12          @ r3<- B
5603    ubfx    r9, rINST, #8, #4           @ r9<- A
5604    GET_VREG(r1, r3)                    @ r1<- vB
5605    GET_VREG(r0, r9)                    @ r0<- vA
5606    .if 0
5607    cmp     r1, #0                      @ is second operand zero?
5608    beq     common_errDivideByZero
5609    .endif
5610    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5611
5612                               @ optional op; may set condition codes
5613    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5614    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5615    SET_VREG(r0, r9)               @ vAA<- r0
5616    GOTO_OPCODE(ip)                     @ jump to next instruction
5617    /* 10-13 instructions */
5618
5619
5620
5621/* ------------------------------ */
5622    .balign 64
5623.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5624/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5625/* File: armv6t2/binop2addr.S */
5626    /*
5627     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5628     * that specifies an instruction that performs "result = r0 op r1".
5629     * This could be an ARM instruction or a function call.  (If the result
5630     * comes back in a register other than r0, you can override "result".)
5631     *
5632     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5633     * vCC (r1).  Useful for integer division and modulus.
5634     *
5635     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5636     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5637     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5638     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5639     */
5640    /* binop/2addr vA, vB */
5641    mov     r3, rINST, lsr #12          @ r3<- B
5642    ubfx    r9, rINST, #8, #4           @ r9<- A
5643    GET_VREG(r1, r3)                    @ r1<- vB
5644    GET_VREG(r0, r9)                    @ r0<- vA
5645    .if 0
5646    cmp     r1, #0                      @ is second operand zero?
5647    beq     common_errDivideByZero
5648    .endif
5649    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5650
5651    and     r1, r1, #31                           @ optional op; may set condition codes
5652    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5654    SET_VREG(r0, r9)               @ vAA<- r0
5655    GOTO_OPCODE(ip)                     @ jump to next instruction
5656    /* 10-13 instructions */
5657
5658
5659
5660/* ------------------------------ */
5661    .balign 64
5662.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5663/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5664/* File: armv6t2/binop2addr.S */
5665    /*
5666     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5667     * that specifies an instruction that performs "result = r0 op r1".
5668     * This could be an ARM instruction or a function call.  (If the result
5669     * comes back in a register other than r0, you can override "result".)
5670     *
5671     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5672     * vCC (r1).  Useful for integer division and modulus.
5673     *
5674     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5675     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5676     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5677     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5678     */
5679    /* binop/2addr vA, vB */
5680    mov     r3, rINST, lsr #12          @ r3<- B
5681    ubfx    r9, rINST, #8, #4           @ r9<- A
5682    GET_VREG(r1, r3)                    @ r1<- vB
5683    GET_VREG(r0, r9)                    @ r0<- vA
5684    .if 0
5685    cmp     r1, #0                      @ is second operand zero?
5686    beq     common_errDivideByZero
5687    .endif
5688    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5689
5690    and     r1, r1, #31                           @ optional op; may set condition codes
5691    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5692    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5693    SET_VREG(r0, r9)               @ vAA<- r0
5694    GOTO_OPCODE(ip)                     @ jump to next instruction
5695    /* 10-13 instructions */
5696
5697
5698
5699/* ------------------------------ */
5700    .balign 64
5701.L_OP_USHR_INT_2ADDR: /* 0xba */
5702/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5703/* File: armv6t2/binop2addr.S */
5704    /*
5705     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5706     * that specifies an instruction that performs "result = r0 op r1".
5707     * This could be an ARM instruction or a function call.  (If the result
5708     * comes back in a register other than r0, you can override "result".)
5709     *
5710     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5711     * vCC (r1).  Useful for integer division and modulus.
5712     *
5713     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5714     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5715     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5716     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5717     */
5718    /* binop/2addr vA, vB */
5719    mov     r3, rINST, lsr #12          @ r3<- B
5720    ubfx    r9, rINST, #8, #4           @ r9<- A
5721    GET_VREG(r1, r3)                    @ r1<- vB
5722    GET_VREG(r0, r9)                    @ r0<- vA
5723    .if 0
5724    cmp     r1, #0                      @ is second operand zero?
5725    beq     common_errDivideByZero
5726    .endif
5727    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5728
5729    and     r1, r1, #31                           @ optional op; may set condition codes
5730    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5731    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5732    SET_VREG(r0, r9)               @ vAA<- r0
5733    GOTO_OPCODE(ip)                     @ jump to next instruction
5734    /* 10-13 instructions */
5735
5736
5737
5738/* ------------------------------ */
5739    .balign 64
5740.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5741/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5742/* File: armv6t2/binopWide2addr.S */
5743    /*
5744     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5745     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5746     * This could be an ARM instruction or a function call.  (If the result
5747     * comes back in a register other than r0, you can override "result".)
5748     *
5749     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5750     * vCC (r1).  Useful for integer division and modulus.
5751     *
5752     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5753     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5754     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5755     *      rem-double/2addr
5756     */
5757    /* binop/2addr vA, vB */
5758    mov     r1, rINST, lsr #12          @ r1<- B
5759    ubfx    r9, rINST, #8, #4           @ r9<- A
5760    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5761    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5762    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5763    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5764    .if 0
5765    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5766    beq     common_errDivideByZero
5767    .endif
5768    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5769
5770    adds    r0, r0, r2                           @ optional op; may set condition codes
5771    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5772    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5773    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5774    GOTO_OPCODE(ip)                     @ jump to next instruction
5775    /* 12-15 instructions */
5776
5777
5778
5779/* ------------------------------ */
5780    .balign 64
5781.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5782/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5783/* File: armv6t2/binopWide2addr.S */
5784    /*
5785     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5786     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5787     * This could be an ARM instruction or a function call.  (If the result
5788     * comes back in a register other than r0, you can override "result".)
5789     *
5790     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5791     * vCC (r1).  Useful for integer division and modulus.
5792     *
5793     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5794     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5795     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5796     *      rem-double/2addr
5797     */
5798    /* binop/2addr vA, vB */
5799    mov     r1, rINST, lsr #12          @ r1<- B
5800    ubfx    r9, rINST, #8, #4           @ r9<- A
5801    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5802    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5803    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5804    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5805    .if 0
5806    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5807    beq     common_errDivideByZero
5808    .endif
5809    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5810
5811    subs    r0, r0, r2                           @ optional op; may set condition codes
5812    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5813    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5814    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5815    GOTO_OPCODE(ip)                     @ jump to next instruction
5816    /* 12-15 instructions */
5817
5818
5819
5820/* ------------------------------ */
5821    .balign 64
5822.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5823/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5824    /*
5825     * Signed 64-bit integer multiply, "/2addr" version.
5826     *
5827     * See OP_MUL_LONG for an explanation.
5828     *
5829     * We get a little tight on registers, so to avoid looking up &fp[A]
5830     * again we stuff it into rINST.
5831     */
5832    /* mul-long/2addr vA, vB */
5833    mov     r1, rINST, lsr #12          @ r1<- B
5834    ubfx    r9, rINST, #8, #4           @ r9<- A
5835    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5836    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5837    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5838    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5839    mul     ip, r2, r1                  @  ip<- ZxW
5840    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5841    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5842    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5843    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5844    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5846    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5847    GOTO_OPCODE(ip)                     @ jump to next instruction
5848
5849
5850/* ------------------------------ */
5851    .balign 64
5852.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5853/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5854/* File: armv6t2/binopWide2addr.S */
5855    /*
5856     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5857     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5858     * This could be an ARM instruction or a function call.  (If the result
5859     * comes back in a register other than r0, you can override "result".)
5860     *
5861     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5862     * vCC (r1).  Useful for integer division and modulus.
5863     *
5864     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5865     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5866     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5867     *      rem-double/2addr
5868     */
5869    /* binop/2addr vA, vB */
5870    mov     r1, rINST, lsr #12          @ r1<- B
5871    ubfx    r9, rINST, #8, #4           @ r9<- A
5872    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5873    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5874    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5875    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5876    .if 1
5877    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5878    beq     common_errDivideByZero
5879    .endif
5880    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5881
5882                               @ optional op; may set condition codes
5883    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5885    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5886    GOTO_OPCODE(ip)                     @ jump to next instruction
5887    /* 12-15 instructions */
5888
5889
5890
5891/* ------------------------------ */
5892    .balign 64
5893.L_OP_REM_LONG_2ADDR: /* 0xbf */
5894/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5895/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5896/* File: armv6t2/binopWide2addr.S */
5897    /*
5898     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5899     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5900     * This could be an ARM instruction or a function call.  (If the result
5901     * comes back in a register other than r0, you can override "result".)
5902     *
5903     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5904     * vCC (r1).  Useful for integer division and modulus.
5905     *
5906     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5907     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5908     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5909     *      rem-double/2addr
5910     */
5911    /* binop/2addr vA, vB */
5912    mov     r1, rINST, lsr #12          @ r1<- B
5913    ubfx    r9, rINST, #8, #4           @ r9<- A
5914    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5915    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5916    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5917    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5918    .if 1
5919    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5920    beq     common_errDivideByZero
5921    .endif
5922    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5923
5924                               @ optional op; may set condition codes
5925    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5926    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5927    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5928    GOTO_OPCODE(ip)                     @ jump to next instruction
5929    /* 12-15 instructions */
5930
5931
5932
5933/* ------------------------------ */
5934    .balign 64
5935.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5936/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5937/* File: armv6t2/binopWide2addr.S */
5938    /*
5939     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5940     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5941     * This could be an ARM instruction or a function call.  (If the result
5942     * comes back in a register other than r0, you can override "result".)
5943     *
5944     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5945     * vCC (r1).  Useful for integer division and modulus.
5946     *
5947     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5948     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5949     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5950     *      rem-double/2addr
5951     */
5952    /* binop/2addr vA, vB */
5953    mov     r1, rINST, lsr #12          @ r1<- B
5954    ubfx    r9, rINST, #8, #4           @ r9<- A
5955    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5956    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5957    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5958    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5959    .if 0
5960    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5961    beq     common_errDivideByZero
5962    .endif
5963    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5964
5965    and     r0, r0, r2                           @ optional op; may set condition codes
5966    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5968    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5969    GOTO_OPCODE(ip)                     @ jump to next instruction
5970    /* 12-15 instructions */
5971
5972
5973
5974/* ------------------------------ */
5975    .balign 64
5976.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5977/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5978/* File: armv6t2/binopWide2addr.S */
5979    /*
5980     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5981     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5982     * This could be an ARM instruction or a function call.  (If the result
5983     * comes back in a register other than r0, you can override "result".)
5984     *
5985     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5986     * vCC (r1).  Useful for integer division and modulus.
5987     *
5988     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5989     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5990     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5991     *      rem-double/2addr
5992     */
5993    /* binop/2addr vA, vB */
5994    mov     r1, rINST, lsr #12          @ r1<- B
5995    ubfx    r9, rINST, #8, #4           @ r9<- A
5996    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5997    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5998    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5999    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6000    .if 0
6001    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6002    beq     common_errDivideByZero
6003    .endif
6004    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6005
6006    orr     r0, r0, r2                           @ optional op; may set condition codes
6007    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6008    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6009    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6010    GOTO_OPCODE(ip)                     @ jump to next instruction
6011    /* 12-15 instructions */
6012
6013
6014
6015/* ------------------------------ */
6016    .balign 64
6017.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6018/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
6019/* File: armv6t2/binopWide2addr.S */
6020    /*
6021     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6022     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6023     * This could be an ARM instruction or a function call.  (If the result
6024     * comes back in a register other than r0, you can override "result".)
6025     *
6026     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6027     * vCC (r1).  Useful for integer division and modulus.
6028     *
6029     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6030     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6031     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6032     *      rem-double/2addr
6033     */
6034    /* binop/2addr vA, vB */
6035    mov     r1, rINST, lsr #12          @ r1<- B
6036    ubfx    r9, rINST, #8, #4           @ r9<- A
6037    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6038    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6039    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6040    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6041    .if 0
6042    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6043    beq     common_errDivideByZero
6044    .endif
6045    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6046
6047    eor     r0, r0, r2                           @ optional op; may set condition codes
6048    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6049    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6050    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6051    GOTO_OPCODE(ip)                     @ jump to next instruction
6052    /* 12-15 instructions */
6053
6054
6055
6056/* ------------------------------ */
6057    .balign 64
6058.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6059/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6060    /*
6061     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6062     * 32-bit shift distance.
6063     */
6064    /* shl-long/2addr vA, vB */
6065    mov     r3, rINST, lsr #12          @ r3<- B
6066    ubfx    r9, rINST, #8, #4           @ r9<- A
6067    GET_VREG(r2, r3)                    @ r2<- vB
6068    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6069    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6070    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6071
6072    mov     r1, r1, asl r2              @  r1<- r1 << r2
6073    rsb     r3, r2, #32                 @  r3<- 32 - r2
6074    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6075    subs    ip, r2, #32                 @  ip<- r2 - 32
6076    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6077    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6078    mov     r0, r0, asl r2              @  r0<- r0 << r2
6079    b       .LOP_SHL_LONG_2ADDR_finish
6080
6081/* ------------------------------ */
6082    .balign 64
6083.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6084/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6085    /*
6086     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6087     * 32-bit shift distance.
6088     */
6089    /* shr-long/2addr vA, vB */
6090    mov     r3, rINST, lsr #12          @ r3<- B
6091    ubfx    r9, rINST, #8, #4           @ r9<- A
6092    GET_VREG(r2, r3)                    @ r2<- vB
6093    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6094    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6095    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6096
6097    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6098    rsb     r3, r2, #32                 @  r3<- 32 - r2
6099    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6100    subs    ip, r2, #32                 @  ip<- r2 - 32
6101    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6102    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6103    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6104    b       .LOP_SHR_LONG_2ADDR_finish
6105
6106/* ------------------------------ */
6107    .balign 64
6108.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6109/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6110    /*
6111     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6112     * 32-bit shift distance.
6113     */
6114    /* ushr-long/2addr vA, vB */
6115    mov     r3, rINST, lsr #12          @ r3<- B
6116    ubfx    r9, rINST, #8, #4           @ r9<- A
6117    GET_VREG(r2, r3)                    @ r2<- vB
6118    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6119    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6120    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6121
6122    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6123    rsb     r3, r2, #32                 @  r3<- 32 - r2
6124    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6125    subs    ip, r2, #32                 @  ip<- r2 - 32
6126    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6127    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6128    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6129    b       .LOP_USHR_LONG_2ADDR_finish
6130
6131/* ------------------------------ */
6132    .balign 64
6133.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6134/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6135/* File: arm-vfp/fbinop2addr.S */
6136    /*
6137     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6138     * an "instr" line that specifies an instruction that performs
6139     * "s2 = s0 op s1".
6140     *
6141     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6142     */
6143    /* binop/2addr vA, vB */
6144    mov     r3, rINST, lsr #12          @ r3<- B
6145    mov     r9, rINST, lsr #8           @ r9<- A+
6146    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6147    and     r9, r9, #15                 @ r9<- A
6148    flds    s1, [r3]                    @ s1<- vB
6149    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6150    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6151    flds    s0, [r9]                    @ s0<- vA
6152
6153    fadds   s2, s0, s1                              @ s2<- op
6154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6155    fsts    s2, [r9]                    @ vAA<- s2
6156    GOTO_OPCODE(ip)                     @ jump to next instruction
6157
6158
6159/* ------------------------------ */
6160    .balign 64
6161.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6162/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6163/* File: arm-vfp/fbinop2addr.S */
6164    /*
6165     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6166     * an "instr" line that specifies an instruction that performs
6167     * "s2 = s0 op s1".
6168     *
6169     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6170     */
6171    /* binop/2addr vA, vB */
6172    mov     r3, rINST, lsr #12          @ r3<- B
6173    mov     r9, rINST, lsr #8           @ r9<- A+
6174    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6175    and     r9, r9, #15                 @ r9<- A
6176    flds    s1, [r3]                    @ s1<- vB
6177    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6178    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6179    flds    s0, [r9]                    @ s0<- vA
6180
6181    fsubs   s2, s0, s1                              @ s2<- op
6182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6183    fsts    s2, [r9]                    @ vAA<- s2
6184    GOTO_OPCODE(ip)                     @ jump to next instruction
6185
6186
6187/* ------------------------------ */
6188    .balign 64
6189.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6190/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6191/* File: arm-vfp/fbinop2addr.S */
6192    /*
6193     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6194     * an "instr" line that specifies an instruction that performs
6195     * "s2 = s0 op s1".
6196     *
6197     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6198     */
6199    /* binop/2addr vA, vB */
6200    mov     r3, rINST, lsr #12          @ r3<- B
6201    mov     r9, rINST, lsr #8           @ r9<- A+
6202    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6203    and     r9, r9, #15                 @ r9<- A
6204    flds    s1, [r3]                    @ s1<- vB
6205    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6206    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6207    flds    s0, [r9]                    @ s0<- vA
6208
6209    fmuls   s2, s0, s1                              @ s2<- op
6210    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6211    fsts    s2, [r9]                    @ vAA<- s2
6212    GOTO_OPCODE(ip)                     @ jump to next instruction
6213
6214
6215/* ------------------------------ */
6216    .balign 64
6217.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6218/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6219/* File: arm-vfp/fbinop2addr.S */
6220    /*
6221     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6222     * an "instr" line that specifies an instruction that performs
6223     * "s2 = s0 op s1".
6224     *
6225     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6226     */
6227    /* binop/2addr vA, vB */
6228    mov     r3, rINST, lsr #12          @ r3<- B
6229    mov     r9, rINST, lsr #8           @ r9<- A+
6230    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6231    and     r9, r9, #15                 @ r9<- A
6232    flds    s1, [r3]                    @ s1<- vB
6233    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6234    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6235    flds    s0, [r9]                    @ s0<- vA
6236
6237    fdivs   s2, s0, s1                              @ s2<- op
6238    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6239    fsts    s2, [r9]                    @ vAA<- s2
6240    GOTO_OPCODE(ip)                     @ jump to next instruction
6241
6242
6243/* ------------------------------ */
6244    .balign 64
6245.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6246/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6247/* EABI doesn't define a float remainder function, but libm does */
6248/* File: armv6t2/binop2addr.S */
6249    /*
6250     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6251     * that specifies an instruction that performs "result = r0 op r1".
6252     * This could be an ARM instruction or a function call.  (If the result
6253     * comes back in a register other than r0, you can override "result".)
6254     *
6255     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6256     * vCC (r1).  Useful for integer division and modulus.
6257     *
6258     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6259     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6260     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6261     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6262     */
6263    /* binop/2addr vA, vB */
6264    mov     r3, rINST, lsr #12          @ r3<- B
6265    ubfx    r9, rINST, #8, #4           @ r9<- A
6266    GET_VREG(r1, r3)                    @ r1<- vB
6267    GET_VREG(r0, r9)                    @ r0<- vA
6268    .if 0
6269    cmp     r1, #0                      @ is second operand zero?
6270    beq     common_errDivideByZero
6271    .endif
6272    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6273
6274                               @ optional op; may set condition codes
6275    bl      fmodf                              @ r0<- op, r0-r3 changed
6276    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6277    SET_VREG(r0, r9)               @ vAA<- r0
6278    GOTO_OPCODE(ip)                     @ jump to next instruction
6279    /* 10-13 instructions */
6280
6281
6282
6283/* ------------------------------ */
6284    .balign 64
6285.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6286/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6287/* File: arm-vfp/fbinopWide2addr.S */
6288    /*
6289     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6290     * an "instr" line that specifies an instruction that performs
6291     * "d2 = d0 op d1".
6292     *
6293     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6294     *      div-double/2addr
6295     */
6296    /* binop/2addr vA, vB */
6297    mov     r3, rINST, lsr #12          @ r3<- B
6298    mov     r9, rINST, lsr #8           @ r9<- A+
6299    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6300    and     r9, r9, #15                 @ r9<- A
6301    fldd    d1, [r3]                    @ d1<- vB
6302    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6303    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6304    fldd    d0, [r9]                    @ d0<- vA
6305
6306    faddd   d2, d0, d1                              @ d2<- op
6307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6308    fstd    d2, [r9]                    @ vAA<- d2
6309    GOTO_OPCODE(ip)                     @ jump to next instruction
6310
6311
6312/* ------------------------------ */
6313    .balign 64
6314.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6315/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6316/* File: arm-vfp/fbinopWide2addr.S */
6317    /*
6318     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6319     * an "instr" line that specifies an instruction that performs
6320     * "d2 = d0 op d1".
6321     *
6322     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6323     *      div-double/2addr
6324     */
6325    /* binop/2addr vA, vB */
6326    mov     r3, rINST, lsr #12          @ r3<- B
6327    mov     r9, rINST, lsr #8           @ r9<- A+
6328    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6329    and     r9, r9, #15                 @ r9<- A
6330    fldd    d1, [r3]                    @ d1<- vB
6331    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6332    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6333    fldd    d0, [r9]                    @ d0<- vA
6334
6335    fsubd   d2, d0, d1                              @ d2<- op
6336    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6337    fstd    d2, [r9]                    @ vAA<- d2
6338    GOTO_OPCODE(ip)                     @ jump to next instruction
6339
6340
6341/* ------------------------------ */
6342    .balign 64
6343.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6344/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6345/* File: arm-vfp/fbinopWide2addr.S */
6346    /*
6347     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6348     * an "instr" line that specifies an instruction that performs
6349     * "d2 = d0 op d1".
6350     *
6351     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6352     *      div-double/2addr
6353     */
6354    /* binop/2addr vA, vB */
6355    mov     r3, rINST, lsr #12          @ r3<- B
6356    mov     r9, rINST, lsr #8           @ r9<- A+
6357    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6358    and     r9, r9, #15                 @ r9<- A
6359    fldd    d1, [r3]                    @ d1<- vB
6360    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6361    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6362    fldd    d0, [r9]                    @ d0<- vA
6363
6364    fmuld   d2, d0, d1                              @ d2<- op
6365    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6366    fstd    d2, [r9]                    @ vAA<- d2
6367    GOTO_OPCODE(ip)                     @ jump to next instruction
6368
6369
6370/* ------------------------------ */
6371    .balign 64
6372.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6373/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6374/* File: arm-vfp/fbinopWide2addr.S */
6375    /*
6376     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6377     * an "instr" line that specifies an instruction that performs
6378     * "d2 = d0 op d1".
6379     *
6380     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6381     *      div-double/2addr
6382     */
6383    /* binop/2addr vA, vB */
6384    mov     r3, rINST, lsr #12          @ r3<- B
6385    mov     r9, rINST, lsr #8           @ r9<- A+
6386    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6387    and     r9, r9, #15                 @ r9<- A
6388    fldd    d1, [r3]                    @ d1<- vB
6389    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6390    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6391    fldd    d0, [r9]                    @ d0<- vA
6392
6393    fdivd   d2, d0, d1                              @ d2<- op
6394    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6395    fstd    d2, [r9]                    @ vAA<- d2
6396    GOTO_OPCODE(ip)                     @ jump to next instruction
6397
6398
6399/* ------------------------------ */
6400    .balign 64
6401.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6402/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6403/* EABI doesn't define a double remainder function, but libm does */
6404/* File: armv6t2/binopWide2addr.S */
6405    /*
6406     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6407     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6408     * This could be an ARM instruction or a function call.  (If the result
6409     * comes back in a register other than r0, you can override "result".)
6410     *
6411     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6412     * vCC (r1).  Useful for integer division and modulus.
6413     *
6414     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6415     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6416     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6417     *      rem-double/2addr
6418     */
6419    /* binop/2addr vA, vB */
6420    mov     r1, rINST, lsr #12          @ r1<- B
6421    ubfx    r9, rINST, #8, #4           @ r9<- A
6422    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6423    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6424    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6425    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6426    .if 0
6427    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6428    beq     common_errDivideByZero
6429    .endif
6430    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6431
6432                               @ optional op; may set condition codes
6433    bl      fmod                              @ result<- op, r0-r3 changed
6434    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6435    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6436    GOTO_OPCODE(ip)                     @ jump to next instruction
6437    /* 12-15 instructions */
6438
6439
6440
6441/* ------------------------------ */
6442    .balign 64
6443.L_OP_ADD_INT_LIT16: /* 0xd0 */
6444/* File: armv6t2/OP_ADD_INT_LIT16.S */
6445/* File: armv6t2/binopLit16.S */
6446    /*
6447     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6448     * that specifies an instruction that performs "result = r0 op r1".
6449     * This could be an ARM instruction or a function call.  (If the result
6450     * comes back in a register other than r0, you can override "result".)
6451     *
6452     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6453     * vCC (r1).  Useful for integer division and modulus.
6454     *
6455     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6456     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6457     */
6458    /* binop/lit16 vA, vB, #+CCCC */
6459    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6460    mov     r2, rINST, lsr #12          @ r2<- B
6461    ubfx    r9, rINST, #8, #4           @ r9<- A
6462    GET_VREG(r0, r2)                    @ r0<- vB
6463    .if 0
6464    cmp     r1, #0                      @ is second operand zero?
6465    beq     common_errDivideByZero
6466    .endif
6467    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6468
6469    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6470    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6471    SET_VREG(r0, r9)               @ vAA<- r0
6472    GOTO_OPCODE(ip)                     @ jump to next instruction
6473    /* 10-13 instructions */
6474
6475
6476
6477/* ------------------------------ */
6478    .balign 64
6479.L_OP_RSUB_INT: /* 0xd1 */
6480/* File: armv6t2/OP_RSUB_INT.S */
6481/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6482/* File: armv6t2/binopLit16.S */
6483    /*
6484     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6485     * that specifies an instruction that performs "result = r0 op r1".
6486     * This could be an ARM instruction or a function call.  (If the result
6487     * comes back in a register other than r0, you can override "result".)
6488     *
6489     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6490     * vCC (r1).  Useful for integer division and modulus.
6491     *
6492     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6493     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6494     */
6495    /* binop/lit16 vA, vB, #+CCCC */
6496    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6497    mov     r2, rINST, lsr #12          @ r2<- B
6498    ubfx    r9, rINST, #8, #4           @ r9<- A
6499    GET_VREG(r0, r2)                    @ r0<- vB
6500    .if 0
6501    cmp     r1, #0                      @ is second operand zero?
6502    beq     common_errDivideByZero
6503    .endif
6504    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6505
6506    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6507    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6508    SET_VREG(r0, r9)               @ vAA<- r0
6509    GOTO_OPCODE(ip)                     @ jump to next instruction
6510    /* 10-13 instructions */
6511
6512
6513
6514/* ------------------------------ */
6515    .balign 64
6516.L_OP_MUL_INT_LIT16: /* 0xd2 */
6517/* File: armv6t2/OP_MUL_INT_LIT16.S */
6518/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6519/* File: armv6t2/binopLit16.S */
6520    /*
6521     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6522     * that specifies an instruction that performs "result = r0 op r1".
6523     * This could be an ARM instruction or a function call.  (If the result
6524     * comes back in a register other than r0, you can override "result".)
6525     *
6526     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6527     * vCC (r1).  Useful for integer division and modulus.
6528     *
6529     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6530     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6531     */
6532    /* binop/lit16 vA, vB, #+CCCC */
6533    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6534    mov     r2, rINST, lsr #12          @ r2<- B
6535    ubfx    r9, rINST, #8, #4           @ r9<- A
6536    GET_VREG(r0, r2)                    @ r0<- vB
6537    .if 0
6538    cmp     r1, #0                      @ is second operand zero?
6539    beq     common_errDivideByZero
6540    .endif
6541    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6542
6543    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6544    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6545    SET_VREG(r0, r9)               @ vAA<- r0
6546    GOTO_OPCODE(ip)                     @ jump to next instruction
6547    /* 10-13 instructions */
6548
6549
6550
6551/* ------------------------------ */
6552    .balign 64
6553.L_OP_DIV_INT_LIT16: /* 0xd3 */
6554/* File: armv6t2/OP_DIV_INT_LIT16.S */
6555/* File: armv6t2/binopLit16.S */
6556    /*
6557     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6558     * that specifies an instruction that performs "result = r0 op r1".
6559     * This could be an ARM instruction or a function call.  (If the result
6560     * comes back in a register other than r0, you can override "result".)
6561     *
6562     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6563     * vCC (r1).  Useful for integer division and modulus.
6564     *
6565     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6566     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6567     */
6568    /* binop/lit16 vA, vB, #+CCCC */
6569    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6570    mov     r2, rINST, lsr #12          @ r2<- B
6571    ubfx    r9, rINST, #8, #4           @ r9<- A
6572    GET_VREG(r0, r2)                    @ r0<- vB
6573    .if 1
6574    cmp     r1, #0                      @ is second operand zero?
6575    beq     common_errDivideByZero
6576    .endif
6577    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6578
6579    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6581    SET_VREG(r0, r9)               @ vAA<- r0
6582    GOTO_OPCODE(ip)                     @ jump to next instruction
6583    /* 10-13 instructions */
6584
6585
6586
6587/* ------------------------------ */
6588    .balign 64
6589.L_OP_REM_INT_LIT16: /* 0xd4 */
6590/* File: armv6t2/OP_REM_INT_LIT16.S */
6591/* idivmod returns quotient in r0 and remainder in r1 */
6592/* File: armv6t2/binopLit16.S */
6593    /*
6594     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6595     * that specifies an instruction that performs "result = r0 op r1".
6596     * This could be an ARM instruction or a function call.  (If the result
6597     * comes back in a register other than r0, you can override "result".)
6598     *
6599     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6600     * vCC (r1).  Useful for integer division and modulus.
6601     *
6602     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6603     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6604     */
6605    /* binop/lit16 vA, vB, #+CCCC */
6606    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6607    mov     r2, rINST, lsr #12          @ r2<- B
6608    ubfx    r9, rINST, #8, #4           @ r9<- A
6609    GET_VREG(r0, r2)                    @ r0<- vB
6610    .if 1
6611    cmp     r1, #0                      @ is second operand zero?
6612    beq     common_errDivideByZero
6613    .endif
6614    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6615
6616    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6617    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6618    SET_VREG(r1, r9)               @ vAA<- r1
6619    GOTO_OPCODE(ip)                     @ jump to next instruction
6620    /* 10-13 instructions */
6621
6622
6623
6624/* ------------------------------ */
6625    .balign 64
6626.L_OP_AND_INT_LIT16: /* 0xd5 */
6627/* File: armv6t2/OP_AND_INT_LIT16.S */
6628/* File: armv6t2/binopLit16.S */
6629    /*
6630     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6631     * that specifies an instruction that performs "result = r0 op r1".
6632     * This could be an ARM instruction or a function call.  (If the result
6633     * comes back in a register other than r0, you can override "result".)
6634     *
6635     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6636     * vCC (r1).  Useful for integer division and modulus.
6637     *
6638     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6639     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6640     */
6641    /* binop/lit16 vA, vB, #+CCCC */
6642    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6643    mov     r2, rINST, lsr #12          @ r2<- B
6644    ubfx    r9, rINST, #8, #4           @ r9<- A
6645    GET_VREG(r0, r2)                    @ r0<- vB
6646    .if 0
6647    cmp     r1, #0                      @ is second operand zero?
6648    beq     common_errDivideByZero
6649    .endif
6650    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6651
6652    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6654    SET_VREG(r0, r9)               @ vAA<- r0
6655    GOTO_OPCODE(ip)                     @ jump to next instruction
6656    /* 10-13 instructions */
6657
6658
6659
6660/* ------------------------------ */
6661    .balign 64
6662.L_OP_OR_INT_LIT16: /* 0xd6 */
6663/* File: armv6t2/OP_OR_INT_LIT16.S */
6664/* File: armv6t2/binopLit16.S */
6665    /*
6666     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6667     * that specifies an instruction that performs "result = r0 op r1".
6668     * This could be an ARM instruction or a function call.  (If the result
6669     * comes back in a register other than r0, you can override "result".)
6670     *
6671     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6672     * vCC (r1).  Useful for integer division and modulus.
6673     *
6674     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6675     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6676     */
6677    /* binop/lit16 vA, vB, #+CCCC */
6678    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6679    mov     r2, rINST, lsr #12          @ r2<- B
6680    ubfx    r9, rINST, #8, #4           @ r9<- A
6681    GET_VREG(r0, r2)                    @ r0<- vB
6682    .if 0
6683    cmp     r1, #0                      @ is second operand zero?
6684    beq     common_errDivideByZero
6685    .endif
6686    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6687
6688    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6689    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6690    SET_VREG(r0, r9)               @ vAA<- r0
6691    GOTO_OPCODE(ip)                     @ jump to next instruction
6692    /* 10-13 instructions */
6693
6694
6695
6696/* ------------------------------ */
6697    .balign 64
6698.L_OP_XOR_INT_LIT16: /* 0xd7 */
6699/* File: armv6t2/OP_XOR_INT_LIT16.S */
6700/* File: armv6t2/binopLit16.S */
6701    /*
6702     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6703     * that specifies an instruction that performs "result = r0 op r1".
6704     * This could be an ARM instruction or a function call.  (If the result
6705     * comes back in a register other than r0, you can override "result".)
6706     *
6707     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6708     * vCC (r1).  Useful for integer division and modulus.
6709     *
6710     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6711     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6712     */
6713    /* binop/lit16 vA, vB, #+CCCC */
6714    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6715    mov     r2, rINST, lsr #12          @ r2<- B
6716    ubfx    r9, rINST, #8, #4           @ r9<- A
6717    GET_VREG(r0, r2)                    @ r0<- vB
6718    .if 0
6719    cmp     r1, #0                      @ is second operand zero?
6720    beq     common_errDivideByZero
6721    .endif
6722    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6723
6724    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6726    SET_VREG(r0, r9)               @ vAA<- r0
6727    GOTO_OPCODE(ip)                     @ jump to next instruction
6728    /* 10-13 instructions */
6729
6730
6731
6732/* ------------------------------ */
6733    .balign 64
6734.L_OP_ADD_INT_LIT8: /* 0xd8 */
6735/* File: armv5te/OP_ADD_INT_LIT8.S */
6736/* File: armv5te/binopLit8.S */
6737    /*
6738     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6739     * that specifies an instruction that performs "result = r0 op r1".
6740     * This could be an ARM instruction or a function call.  (If the result
6741     * comes back in a register other than r0, you can override "result".)
6742     *
6743     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6744     * vCC (r1).  Useful for integer division and modulus.
6745     *
6746     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6747     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6748     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6749     */
6750    /* binop/lit8 vAA, vBB, #+CC */
6751    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6752    mov     r9, rINST, lsr #8           @ r9<- AA
6753    and     r2, r3, #255                @ r2<- BB
6754    GET_VREG(r0, r2)                    @ r0<- vBB
6755    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6756    .if 0
6757    @cmp     r1, #0                      @ is second operand zero?
6758    beq     common_errDivideByZero
6759    .endif
6760    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6761
6762                               @ optional op; may set condition codes
6763    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6764    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6765    SET_VREG(r0, r9)               @ vAA<- r0
6766    GOTO_OPCODE(ip)                     @ jump to next instruction
6767    /* 10-12 instructions */
6768
6769
6770
6771/* ------------------------------ */
6772    .balign 64
6773.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6774/* File: armv5te/OP_RSUB_INT_LIT8.S */
6775/* File: armv5te/binopLit8.S */
6776    /*
6777     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6778     * that specifies an instruction that performs "result = r0 op r1".
6779     * This could be an ARM instruction or a function call.  (If the result
6780     * comes back in a register other than r0, you can override "result".)
6781     *
6782     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6783     * vCC (r1).  Useful for integer division and modulus.
6784     *
6785     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6786     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6787     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6788     */
6789    /* binop/lit8 vAA, vBB, #+CC */
6790    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6791    mov     r9, rINST, lsr #8           @ r9<- AA
6792    and     r2, r3, #255                @ r2<- BB
6793    GET_VREG(r0, r2)                    @ r0<- vBB
6794    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6795    .if 0
6796    @cmp     r1, #0                      @ is second operand zero?
6797    beq     common_errDivideByZero
6798    .endif
6799    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6800
6801                               @ optional op; may set condition codes
6802    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6804    SET_VREG(r0, r9)               @ vAA<- r0
6805    GOTO_OPCODE(ip)                     @ jump to next instruction
6806    /* 10-12 instructions */
6807
6808
6809
6810/* ------------------------------ */
6811    .balign 64
6812.L_OP_MUL_INT_LIT8: /* 0xda */
6813/* File: armv5te/OP_MUL_INT_LIT8.S */
6814/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6815/* File: armv5te/binopLit8.S */
6816    /*
6817     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6818     * that specifies an instruction that performs "result = r0 op r1".
6819     * This could be an ARM instruction or a function call.  (If the result
6820     * comes back in a register other than r0, you can override "result".)
6821     *
6822     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6823     * vCC (r1).  Useful for integer division and modulus.
6824     *
6825     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6826     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6827     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6828     */
6829    /* binop/lit8 vAA, vBB, #+CC */
6830    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6831    mov     r9, rINST, lsr #8           @ r9<- AA
6832    and     r2, r3, #255                @ r2<- BB
6833    GET_VREG(r0, r2)                    @ r0<- vBB
6834    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6835    .if 0
6836    @cmp     r1, #0                      @ is second operand zero?
6837    beq     common_errDivideByZero
6838    .endif
6839    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6840
6841                               @ optional op; may set condition codes
6842    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6844    SET_VREG(r0, r9)               @ vAA<- r0
6845    GOTO_OPCODE(ip)                     @ jump to next instruction
6846    /* 10-12 instructions */
6847
6848
6849
6850/* ------------------------------ */
6851    .balign 64
6852.L_OP_DIV_INT_LIT8: /* 0xdb */
6853/* File: armv5te/OP_DIV_INT_LIT8.S */
6854/* File: armv5te/binopLit8.S */
6855    /*
6856     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6857     * that specifies an instruction that performs "result = r0 op r1".
6858     * This could be an ARM instruction or a function call.  (If the result
6859     * comes back in a register other than r0, you can override "result".)
6860     *
6861     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6862     * vCC (r1).  Useful for integer division and modulus.
6863     *
6864     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6865     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6866     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6867     */
6868    /* binop/lit8 vAA, vBB, #+CC */
6869    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6870    mov     r9, rINST, lsr #8           @ r9<- AA
6871    and     r2, r3, #255                @ r2<- BB
6872    GET_VREG(r0, r2)                    @ r0<- vBB
6873    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6874    .if 1
6875    @cmp     r1, #0                      @ is second operand zero?
6876    beq     common_errDivideByZero
6877    .endif
6878    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6879
6880                               @ optional op; may set condition codes
6881    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6882    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6883    SET_VREG(r0, r9)               @ vAA<- r0
6884    GOTO_OPCODE(ip)                     @ jump to next instruction
6885    /* 10-12 instructions */
6886
6887
6888
6889/* ------------------------------ */
6890    .balign 64
6891.L_OP_REM_INT_LIT8: /* 0xdc */
6892/* File: armv5te/OP_REM_INT_LIT8.S */
6893/* idivmod returns quotient in r0 and remainder in r1 */
6894/* File: armv5te/binopLit8.S */
6895    /*
6896     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6897     * that specifies an instruction that performs "result = r0 op r1".
6898     * This could be an ARM instruction or a function call.  (If the result
6899     * comes back in a register other than r0, you can override "result".)
6900     *
6901     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6902     * vCC (r1).  Useful for integer division and modulus.
6903     *
6904     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6905     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6906     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6907     */
6908    /* binop/lit8 vAA, vBB, #+CC */
6909    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6910    mov     r9, rINST, lsr #8           @ r9<- AA
6911    and     r2, r3, #255                @ r2<- BB
6912    GET_VREG(r0, r2)                    @ r0<- vBB
6913    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6914    .if 1
6915    @cmp     r1, #0                      @ is second operand zero?
6916    beq     common_errDivideByZero
6917    .endif
6918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6919
6920                               @ optional op; may set condition codes
6921    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6923    SET_VREG(r1, r9)               @ vAA<- r1
6924    GOTO_OPCODE(ip)                     @ jump to next instruction
6925    /* 10-12 instructions */
6926
6927
6928
6929/* ------------------------------ */
6930    .balign 64
6931.L_OP_AND_INT_LIT8: /* 0xdd */
6932/* File: armv5te/OP_AND_INT_LIT8.S */
6933/* File: armv5te/binopLit8.S */
6934    /*
6935     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6936     * that specifies an instruction that performs "result = r0 op r1".
6937     * This could be an ARM instruction or a function call.  (If the result
6938     * comes back in a register other than r0, you can override "result".)
6939     *
6940     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6941     * vCC (r1).  Useful for integer division and modulus.
6942     *
6943     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6944     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6945     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6946     */
6947    /* binop/lit8 vAA, vBB, #+CC */
6948    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6949    mov     r9, rINST, lsr #8           @ r9<- AA
6950    and     r2, r3, #255                @ r2<- BB
6951    GET_VREG(r0, r2)                    @ r0<- vBB
6952    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6953    .if 0
6954    @cmp     r1, #0                      @ is second operand zero?
6955    beq     common_errDivideByZero
6956    .endif
6957    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6958
6959                               @ optional op; may set condition codes
6960    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6962    SET_VREG(r0, r9)               @ vAA<- r0
6963    GOTO_OPCODE(ip)                     @ jump to next instruction
6964    /* 10-12 instructions */
6965
6966
6967
6968/* ------------------------------ */
6969    .balign 64
6970.L_OP_OR_INT_LIT8: /* 0xde */
6971/* File: armv5te/OP_OR_INT_LIT8.S */
6972/* File: armv5te/binopLit8.S */
6973    /*
6974     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6975     * that specifies an instruction that performs "result = r0 op r1".
6976     * This could be an ARM instruction or a function call.  (If the result
6977     * comes back in a register other than r0, you can override "result".)
6978     *
6979     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6980     * vCC (r1).  Useful for integer division and modulus.
6981     *
6982     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6983     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6984     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6985     */
6986    /* binop/lit8 vAA, vBB, #+CC */
6987    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6988    mov     r9, rINST, lsr #8           @ r9<- AA
6989    and     r2, r3, #255                @ r2<- BB
6990    GET_VREG(r0, r2)                    @ r0<- vBB
6991    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6992    .if 0
6993    @cmp     r1, #0                      @ is second operand zero?
6994    beq     common_errDivideByZero
6995    .endif
6996    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6997
6998                               @ optional op; may set condition codes
6999    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7000    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7001    SET_VREG(r0, r9)               @ vAA<- r0
7002    GOTO_OPCODE(ip)                     @ jump to next instruction
7003    /* 10-12 instructions */
7004
7005
7006
7007/* ------------------------------ */
7008    .balign 64
7009.L_OP_XOR_INT_LIT8: /* 0xdf */
7010/* File: armv5te/OP_XOR_INT_LIT8.S */
7011/* File: armv5te/binopLit8.S */
7012    /*
7013     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7014     * that specifies an instruction that performs "result = r0 op r1".
7015     * This could be an ARM instruction or a function call.  (If the result
7016     * comes back in a register other than r0, you can override "result".)
7017     *
7018     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7019     * vCC (r1).  Useful for integer division and modulus.
7020     *
7021     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7022     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7023     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7024     */
7025    /* binop/lit8 vAA, vBB, #+CC */
7026    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7027    mov     r9, rINST, lsr #8           @ r9<- AA
7028    and     r2, r3, #255                @ r2<- BB
7029    GET_VREG(r0, r2)                    @ r0<- vBB
7030    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7031    .if 0
7032    @cmp     r1, #0                      @ is second operand zero?
7033    beq     common_errDivideByZero
7034    .endif
7035    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7036
7037                               @ optional op; may set condition codes
7038    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7039    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7040    SET_VREG(r0, r9)               @ vAA<- r0
7041    GOTO_OPCODE(ip)                     @ jump to next instruction
7042    /* 10-12 instructions */
7043
7044
7045
7046/* ------------------------------ */
7047    .balign 64
7048.L_OP_SHL_INT_LIT8: /* 0xe0 */
7049/* File: armv5te/OP_SHL_INT_LIT8.S */
7050/* File: armv5te/binopLit8.S */
7051    /*
7052     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7053     * that specifies an instruction that performs "result = r0 op r1".
7054     * This could be an ARM instruction or a function call.  (If the result
7055     * comes back in a register other than r0, you can override "result".)
7056     *
7057     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7058     * vCC (r1).  Useful for integer division and modulus.
7059     *
7060     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7061     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7062     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7063     */
7064    /* binop/lit8 vAA, vBB, #+CC */
7065    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7066    mov     r9, rINST, lsr #8           @ r9<- AA
7067    and     r2, r3, #255                @ r2<- BB
7068    GET_VREG(r0, r2)                    @ r0<- vBB
7069    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7070    .if 0
7071    @cmp     r1, #0                      @ is second operand zero?
7072    beq     common_errDivideByZero
7073    .endif
7074    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7075
7076    and     r1, r1, #31                           @ optional op; may set condition codes
7077    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7079    SET_VREG(r0, r9)               @ vAA<- r0
7080    GOTO_OPCODE(ip)                     @ jump to next instruction
7081    /* 10-12 instructions */
7082
7083
7084
7085/* ------------------------------ */
7086    .balign 64
7087.L_OP_SHR_INT_LIT8: /* 0xe1 */
7088/* File: armv5te/OP_SHR_INT_LIT8.S */
7089/* File: armv5te/binopLit8.S */
7090    /*
7091     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7092     * that specifies an instruction that performs "result = r0 op r1".
7093     * This could be an ARM instruction or a function call.  (If the result
7094     * comes back in a register other than r0, you can override "result".)
7095     *
7096     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7097     * vCC (r1).  Useful for integer division and modulus.
7098     *
7099     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7100     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7101     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7102     */
7103    /* binop/lit8 vAA, vBB, #+CC */
7104    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7105    mov     r9, rINST, lsr #8           @ r9<- AA
7106    and     r2, r3, #255                @ r2<- BB
7107    GET_VREG(r0, r2)                    @ r0<- vBB
7108    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7109    .if 0
7110    @cmp     r1, #0                      @ is second operand zero?
7111    beq     common_errDivideByZero
7112    .endif
7113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7114
7115    and     r1, r1, #31                           @ optional op; may set condition codes
7116    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7117    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7118    SET_VREG(r0, r9)               @ vAA<- r0
7119    GOTO_OPCODE(ip)                     @ jump to next instruction
7120    /* 10-12 instructions */
7121
7122
7123
7124/* ------------------------------ */
7125    .balign 64
7126.L_OP_USHR_INT_LIT8: /* 0xe2 */
7127/* File: armv5te/OP_USHR_INT_LIT8.S */
7128/* File: armv5te/binopLit8.S */
7129    /*
7130     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7131     * that specifies an instruction that performs "result = r0 op r1".
7132     * This could be an ARM instruction or a function call.  (If the result
7133     * comes back in a register other than r0, you can override "result".)
7134     *
7135     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7136     * vCC (r1).  Useful for integer division and modulus.
7137     *
7138     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7139     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7140     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7141     */
7142    /* binop/lit8 vAA, vBB, #+CC */
7143    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7144    mov     r9, rINST, lsr #8           @ r9<- AA
7145    and     r2, r3, #255                @ r2<- BB
7146    GET_VREG(r0, r2)                    @ r0<- vBB
7147    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7148    .if 0
7149    @cmp     r1, #0                      @ is second operand zero?
7150    beq     common_errDivideByZero
7151    .endif
7152    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7153
7154    and     r1, r1, #31                           @ optional op; may set condition codes
7155    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7156    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7157    SET_VREG(r0, r9)               @ vAA<- r0
7158    GOTO_OPCODE(ip)                     @ jump to next instruction
7159    /* 10-12 instructions */
7160
7161
7162
7163/* ------------------------------ */
7164    .balign 64
7165.L_OP_UNUSED_E3: /* 0xe3 */
7166/* File: armv5te/OP_UNUSED_E3.S */
7167/* File: armv5te/unused.S */
7168    bl      common_abort
7169
7170
7171
7172/* ------------------------------ */
7173    .balign 64
7174.L_OP_UNUSED_E4: /* 0xe4 */
7175/* File: armv5te/OP_UNUSED_E4.S */
7176/* File: armv5te/unused.S */
7177    bl      common_abort
7178
7179
7180
7181/* ------------------------------ */
7182    .balign 64
7183.L_OP_UNUSED_E5: /* 0xe5 */
7184/* File: armv5te/OP_UNUSED_E5.S */
7185/* File: armv5te/unused.S */
7186    bl      common_abort
7187
7188
7189
7190/* ------------------------------ */
7191    .balign 64
7192.L_OP_UNUSED_E6: /* 0xe6 */
7193/* File: armv5te/OP_UNUSED_E6.S */
7194/* File: armv5te/unused.S */
7195    bl      common_abort
7196
7197
7198
7199/* ------------------------------ */
7200    .balign 64
7201.L_OP_UNUSED_E7: /* 0xe7 */
7202/* File: armv5te/OP_UNUSED_E7.S */
7203/* File: armv5te/unused.S */
7204    bl      common_abort
7205
7206
7207
7208/* ------------------------------ */
7209    .balign 64
7210.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7211/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7212/* File: armv5te/OP_IGET_WIDE.S */
7213    /*
7214     * Wide 32-bit instance field get.
7215     */
7216    /* iget-wide vA, vB, field@CCCC */
7217    mov     r0, rINST, lsr #12          @ r0<- B
7218    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7219    FETCH(r1, 1)                        @ r1<- field ref CCCC
7220    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7221    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7222    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7223    cmp     r0, #0                      @ is resolved entry null?
7224    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72258:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7226    EXPORT_PC()                         @ resolve() could throw
7227    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7228    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7229    cmp     r0, #0
7230    bne     .LOP_IGET_WIDE_VOLATILE_finish
7231    b       common_exceptionThrown
7232
7233
7234/* ------------------------------ */
7235    .balign 64
7236.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7237/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7238/* File: armv5te/OP_IPUT_WIDE.S */
7239    /* iput-wide vA, vB, field@CCCC */
7240    mov     r0, rINST, lsr #12          @ r0<- B
7241    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7242    FETCH(r1, 1)                        @ r1<- field ref CCCC
7243    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7244    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7245    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7246    cmp     r0, #0                      @ is resolved entry null?
7247    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72488:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7249    EXPORT_PC()                         @ resolve() could throw
7250    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7251    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7252    cmp     r0, #0                      @ success?
7253    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7254    b       common_exceptionThrown
7255
7256
7257/* ------------------------------ */
7258    .balign 64
7259.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7260/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7261/* File: armv5te/OP_SGET_WIDE.S */
7262    /*
7263     * 64-bit SGET handler.
7264     */
7265    /* sget-wide vAA, field@BBBB */
7266    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7267    FETCH(r1, 1)                        @ r1<- field ref BBBB
7268    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7269    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7270    cmp     r0, #0                      @ is resolved entry null?
7271    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7272.LOP_SGET_WIDE_VOLATILE_finish:
7273    mov     r9, rINST, lsr #8           @ r9<- AA
7274    .if 1
7275    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7276    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
7277    .else
7278    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7279    .endif
7280    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7282    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7284    GOTO_OPCODE(ip)                     @ jump to next instruction
7285
7286
7287/* ------------------------------ */
7288    .balign 64
7289.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7290/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7291/* File: armv5te/OP_SPUT_WIDE.S */
7292    /*
7293     * 64-bit SPUT handler.
7294     */
7295    /* sput-wide vAA, field@BBBB */
7296    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7297    FETCH(r1, 1)                        @ r1<- field ref BBBB
7298    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7299    mov     r9, rINST, lsr #8           @ r9<- AA
7300    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7301    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7302    cmp     r2, #0                      @ is resolved entry null?
7303    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7304.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7305    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7306    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7307    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7308    .if 1
7309    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7310    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
7311    .else
7312    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7313    .endif
7314    GOTO_OPCODE(r10)                    @ jump to next instruction
7315
7316
7317/* ------------------------------ */
7318    .balign 64
7319.L_OP_BREAKPOINT: /* 0xec */
7320/* File: armv5te/OP_BREAKPOINT.S */
7321/* File: armv5te/unused.S */
7322    bl      common_abort
7323
7324
7325
7326/* ------------------------------ */
7327    .balign 64
7328.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7329/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7330    /*
7331     * Handle a throw-verification-error instruction.  This throws an
7332     * exception for an error discovered during verification.  The
7333     * exception is indicated by AA, with some detail provided by BBBB.
7334     */
7335    /* op AA, ref@BBBB */
7336    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7337    FETCH(r2, 1)                        @ r2<- BBBB
7338    EXPORT_PC()                         @ export the PC
7339    mov     r1, rINST, lsr #8           @ r1<- AA
7340    bl      dvmThrowVerificationError   @ always throws
7341    b       common_exceptionThrown      @ handle exception
7342
7343
7344/* ------------------------------ */
7345    .balign 64
7346.L_OP_EXECUTE_INLINE: /* 0xee */
7347/* File: armv5te/OP_EXECUTE_INLINE.S */
7348    /*
7349     * Execute a "native inline" instruction.
7350     *
7351     * We need to call an InlineOp4Func:
7352     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7353     *
7354     * The first four args are in r0-r3, pointer to return value storage
7355     * is on the stack.  The function's return value is a flag that tells
7356     * us if an exception was thrown.
7357     */
7358    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7359    FETCH(r10, 1)                       @ r10<- BBBB
7360    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7361    EXPORT_PC()                         @ can throw
7362    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7363    mov     r0, rINST, lsr #12          @ r0<- B
7364    str     r1, [sp]                    @ push &glue->retval
7365    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7366    add     sp, sp, #8                  @ pop stack
7367    cmp     r0, #0                      @ test boolean result of inline
7368    beq     common_exceptionThrown      @ returned false, handle exception
7369    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7371    GOTO_OPCODE(ip)                     @ jump to next instruction
7372
7373/* ------------------------------ */
7374    .balign 64
7375.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7376/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7377    /*
7378     * Execute a "native inline" instruction, using "/range" semantics.
7379     * Same idea as execute-inline, but we get the args differently.
7380     *
7381     * We need to call an InlineOp4Func:
7382     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7383     *
7384     * The first four args are in r0-r3, pointer to return value storage
7385     * is on the stack.  The function's return value is a flag that tells
7386     * us if an exception was thrown.
7387     */
7388    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7389    FETCH(r10, 1)                       @ r10<- BBBB
7390    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7391    EXPORT_PC()                         @ can throw
7392    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7393    mov     r0, rINST, lsr #8           @ r0<- AA
7394    str     r1, [sp]                    @ push &glue->retval
7395    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7396    add     sp, sp, #8                  @ pop stack
7397    cmp     r0, #0                      @ test boolean result of inline
7398    beq     common_exceptionThrown      @ returned false, handle exception
7399    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7400    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7401    GOTO_OPCODE(ip)                     @ jump to next instruction
7402
7403/* ------------------------------ */
7404    .balign 64
7405.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7406/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7407    /*
7408     * invoke-direct-empty is a no-op in a "standard" interpreter.
7409     */
7410    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7411    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7412    GOTO_OPCODE(ip)                     @ execute it
7413
7414/* ------------------------------ */
7415    .balign 64
7416.L_OP_UNUSED_F1: /* 0xf1 */
7417/* File: armv5te/OP_UNUSED_F1.S */
7418/* File: armv5te/unused.S */
7419    bl      common_abort
7420
7421
7422
7423/* ------------------------------ */
7424    .balign 64
7425.L_OP_IGET_QUICK: /* 0xf2 */
7426/* File: armv6t2/OP_IGET_QUICK.S */
7427    /* For: iget-quick, iget-object-quick */
7428    /* op vA, vB, offset@CCCC */
7429    mov     r2, rINST, lsr #12          @ r2<- B
7430    FETCH(r1, 1)                        @ r1<- field byte offset
7431    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7432    ubfx    r2, rINST, #8, #4           @ r2<- A
7433    cmp     r3, #0                      @ check object for null
7434    beq     common_errNullObject        @ object was null
7435    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7438    SET_VREG(r0, r2)                    @ fp[A]<- r0
7439    GOTO_OPCODE(ip)                     @ jump to next instruction
7440
7441
7442/* ------------------------------ */
7443    .balign 64
7444.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7445/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7446    /* iget-wide-quick vA, vB, offset@CCCC */
7447    mov     r2, rINST, lsr #12          @ r2<- B
7448    FETCH(r1, 1)                        @ r1<- field byte offset
7449    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7450    ubfx    r2, rINST, #8, #4           @ r2<- A
7451    cmp     r3, #0                      @ check object for null
7452    beq     common_errNullObject        @ object was null
7453    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7455    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7457    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7458    GOTO_OPCODE(ip)                     @ jump to next instruction
7459
7460
7461/* ------------------------------ */
7462    .balign 64
7463.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7464/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7465/* File: armv5te/OP_IGET_QUICK.S */
7466    /* For: iget-quick, iget-object-quick */
7467    /* op vA, vB, offset@CCCC */
7468    mov     r2, rINST, lsr #12          @ r2<- B
7469    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7470    FETCH(r1, 1)                        @ r1<- field byte offset
7471    cmp     r3, #0                      @ check object for null
7472    mov     r2, rINST, lsr #8           @ r2<- A(+)
7473    beq     common_errNullObject        @ object was null
7474    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7475    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7476    and     r2, r2, #15
7477    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7478    SET_VREG(r0, r2)                    @ fp[A]<- r0
7479    GOTO_OPCODE(ip)                     @ jump to next instruction
7480
7481
7482
7483/* ------------------------------ */
7484    .balign 64
7485.L_OP_IPUT_QUICK: /* 0xf5 */
7486/* File: armv6t2/OP_IPUT_QUICK.S */
7487    /* For: iput-quick, iput-object-quick */
7488    /* op vA, vB, offset@CCCC */
7489    mov     r2, rINST, lsr #12          @ r2<- B
7490    FETCH(r1, 1)                        @ r1<- field byte offset
7491    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7492    ubfx    r2, rINST, #8, #4           @ r2<- A
7493    cmp     r3, #0                      @ check object for null
7494    beq     common_errNullObject        @ object was null
7495    GET_VREG(r0, r2)                    @ r0<- fp[A]
7496    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7497    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7498    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7499    GOTO_OPCODE(ip)                     @ jump to next instruction
7500
7501
7502/* ------------------------------ */
7503    .balign 64
7504.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7505/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7506    /* iput-wide-quick vA, vB, offset@CCCC */
7507    mov     r1, rINST, lsr #12          @ r1<- B
7508    ubfx    r0, rINST, #8, #4           @ r0<- A
7509    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7510    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7511    cmp     r2, #0                      @ check object for null
7512    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7513    beq     common_errNullObject        @ object was null
7514    FETCH(r3, 1)                        @ r3<- field byte offset
7515    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7516    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7517    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7518    GOTO_OPCODE(ip)                     @ jump to next instruction
7519
7520
7521/* ------------------------------ */
7522    .balign 64
7523.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7524/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7525/* File: armv5te/OP_IPUT_QUICK.S */
7526    /* For: iput-quick, iput-object-quick */
7527    /* op vA, vB, offset@CCCC */
7528    mov     r2, rINST, lsr #12          @ r2<- B
7529    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7530    FETCH(r1, 1)                        @ r1<- field byte offset
7531    cmp     r3, #0                      @ check object for null
7532    mov     r2, rINST, lsr #8           @ r2<- A(+)
7533    beq     common_errNullObject        @ object was null
7534    and     r2, r2, #15
7535    GET_VREG(r0, r2)                    @ r0<- fp[A]
7536    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7537    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7538    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7539    GOTO_OPCODE(ip)                     @ jump to next instruction
7540
7541
7542
7543/* ------------------------------ */
7544    .balign 64
7545.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7546/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7547    /*
7548     * Handle an optimized virtual method call.
7549     *
7550     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7551     */
7552    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7553    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7554    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7555    FETCH(r1, 1)                        @ r1<- BBBB
7556    .if     (!0)
7557    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7558    .endif
7559    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7560    cmp     r2, #0                      @ is "this" null?
7561    beq     common_errNullObject        @ null "this", throw exception
7562    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7563    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7564    EXPORT_PC()                         @ invoke must export
7565    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7566    bl      common_invokeMethodNoRange @ continue on
7567
7568/* ------------------------------ */
7569    .balign 64
7570.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7571/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7572/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7573    /*
7574     * Handle an optimized virtual method call.
7575     *
7576     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7577     */
7578    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7579    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7580    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7581    FETCH(r1, 1)                        @ r1<- BBBB
7582    .if     (!1)
7583    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7584    .endif
7585    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7586    cmp     r2, #0                      @ is "this" null?
7587    beq     common_errNullObject        @ null "this", throw exception
7588    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7589    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7590    EXPORT_PC()                         @ invoke must export
7591    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7592    bl      common_invokeMethodRange @ continue on
7593
7594
7595/* ------------------------------ */
7596    .balign 64
7597.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7598/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7599    /*
7600     * Handle an optimized "super" method call.
7601     *
7602     * for: [opt] invoke-super-quick, invoke-super-quick/range
7603     */
7604    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7605    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7606    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7607    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7608    .if     (!0)
7609    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7610    .endif
7611    FETCH(r1, 1)                        @ r1<- BBBB
7612    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7613    EXPORT_PC()                         @ must export for invoke
7614    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7615    GET_VREG(r3, r10)                   @ r3<- "this"
7616    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7617    cmp     r3, #0                      @ null "this" ref?
7618    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7619    beq     common_errNullObject        @ "this" is null, throw exception
7620    bl      common_invokeMethodNoRange @ continue on
7621
7622
7623/* ------------------------------ */
7624    .balign 64
7625.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7626/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7627/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7628    /*
7629     * Handle an optimized "super" method call.
7630     *
7631     * for: [opt] invoke-super-quick, invoke-super-quick/range
7632     */
7633    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7634    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7635    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7636    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7637    .if     (!1)
7638    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7639    .endif
7640    FETCH(r1, 1)                        @ r1<- BBBB
7641    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7642    EXPORT_PC()                         @ must export for invoke
7643    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7644    GET_VREG(r3, r10)                   @ r3<- "this"
7645    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7646    cmp     r3, #0                      @ null "this" ref?
7647    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7648    beq     common_errNullObject        @ "this" is null, throw exception
7649    bl      common_invokeMethodRange @ continue on
7650
7651
7652
7653/* ------------------------------ */
7654    .balign 64
7655.L_OP_UNUSED_FC: /* 0xfc */
7656/* File: armv5te/OP_UNUSED_FC.S */
7657/* File: armv5te/unused.S */
7658    bl      common_abort
7659
7660
7661
7662/* ------------------------------ */
7663    .balign 64
7664.L_OP_UNUSED_FD: /* 0xfd */
7665/* File: armv5te/OP_UNUSED_FD.S */
7666/* File: armv5te/unused.S */
7667    bl      common_abort
7668
7669
7670
7671/* ------------------------------ */
7672    .balign 64
7673.L_OP_UNUSED_FE: /* 0xfe */
7674/* File: armv5te/OP_UNUSED_FE.S */
7675/* File: armv5te/unused.S */
7676    bl      common_abort
7677
7678
7679
7680/* ------------------------------ */
7681    .balign 64
7682.L_OP_UNUSED_FF: /* 0xff */
7683/* File: armv5te/OP_UNUSED_FF.S */
7684/* File: armv5te/unused.S */
7685    bl      common_abort
7686
7687
7688
7689
7690    .balign 64
7691    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7692    .global dvmAsmInstructionEnd
7693dvmAsmInstructionEnd:
7694
7695/*
7696 * ===========================================================================
7697 *  Sister implementations
7698 * ===========================================================================
7699 */
7700    .global dvmAsmSisterStart
7701    .type   dvmAsmSisterStart, %function
7702    .text
7703    .balign 4
7704dvmAsmSisterStart:
7705
7706/* continuation for OP_CONST_STRING */
7707
7708    /*
7709     * Continuation if the String has not yet been resolved.
7710     *  r1: BBBB (String ref)
7711     *  r9: target register
7712     */
7713.LOP_CONST_STRING_resolve:
7714    EXPORT_PC()
7715    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7716    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7717    bl      dvmResolveString            @ r0<- String reference
7718    cmp     r0, #0                      @ failed?
7719    beq     common_exceptionThrown      @ yup, handle the exception
7720    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7722    SET_VREG(r0, r9)                    @ vAA<- r0
7723    GOTO_OPCODE(ip)                     @ jump to next instruction
7724
7725
7726/* continuation for OP_CONST_STRING_JUMBO */
7727
7728    /*
7729     * Continuation if the String has not yet been resolved.
7730     *  r1: BBBBBBBB (String ref)
7731     *  r9: target register
7732     */
7733.LOP_CONST_STRING_JUMBO_resolve:
7734    EXPORT_PC()
7735    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7736    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7737    bl      dvmResolveString            @ r0<- String reference
7738    cmp     r0, #0                      @ failed?
7739    beq     common_exceptionThrown      @ yup, handle the exception
7740    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7741    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7742    SET_VREG(r0, r9)                    @ vAA<- r0
7743    GOTO_OPCODE(ip)                     @ jump to next instruction
7744
7745
7746/* continuation for OP_CONST_CLASS */
7747
7748    /*
7749     * Continuation if the Class has not yet been resolved.
7750     *  r1: BBBB (Class ref)
7751     *  r9: target register
7752     */
7753.LOP_CONST_CLASS_resolve:
7754    EXPORT_PC()
7755    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7756    mov     r2, #1                      @ r2<- true
7757    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7758    bl      dvmResolveClass             @ r0<- Class reference
7759    cmp     r0, #0                      @ failed?
7760    beq     common_exceptionThrown      @ yup, handle the exception
7761    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7763    SET_VREG(r0, r9)                    @ vAA<- r0
7764    GOTO_OPCODE(ip)                     @ jump to next instruction
7765
7766
7767/* continuation for OP_CHECK_CAST */
7768
7769    /*
7770     * Trivial test failed, need to perform full check.  This is common.
7771     *  r0 holds obj->clazz
7772     *  r1 holds class resolved from BBBB
7773     *  r9 holds object
7774     */
7775.LOP_CHECK_CAST_fullcheck:
7776    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7777    cmp     r0, #0                      @ failed?
7778    bne     .LOP_CHECK_CAST_okay            @ no, success
7779
7780    @ A cast has failed.  We need to throw a ClassCastException with the
7781    @ class of the object that failed to be cast.
7782    EXPORT_PC()                         @ about to throw
7783    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7784    ldr     r0, .LstrClassCastExceptionPtr
7785    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7786    bl      dvmThrowExceptionWithClassMessage
7787    b       common_exceptionThrown
7788
7789    /*
7790     * Resolution required.  This is the least-likely path.
7791     *
7792     *  r2 holds BBBB
7793     *  r9 holds object
7794     */
7795.LOP_CHECK_CAST_resolve:
7796    EXPORT_PC()                         @ resolve() could throw
7797    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7798    mov     r1, r2                      @ r1<- BBBB
7799    mov     r2, #0                      @ r2<- false
7800    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7801    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7802    cmp     r0, #0                      @ got null?
7803    beq     common_exceptionThrown      @ yes, handle exception
7804    mov     r1, r0                      @ r1<- class resolved from BBB
7805    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7806    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7807
7808.LstrClassCastExceptionPtr:
7809    .word   .LstrClassCastException
7810
7811
7812/* continuation for OP_INSTANCE_OF */
7813
7814    /*
7815     * Trivial test failed, need to perform full check.  This is common.
7816     *  r0 holds obj->clazz
7817     *  r1 holds class resolved from BBBB
7818     *  r9 holds A
7819     */
7820.LOP_INSTANCE_OF_fullcheck:
7821    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7822    @ fall through to OP_INSTANCE_OF_store
7823
7824    /*
7825     * r0 holds boolean result
7826     * r9 holds A
7827     */
7828.LOP_INSTANCE_OF_store:
7829    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7830    SET_VREG(r0, r9)                    @ vA<- r0
7831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7832    GOTO_OPCODE(ip)                     @ jump to next instruction
7833
7834    /*
7835     * Trivial test succeeded, save and bail.
7836     *  r9 holds A
7837     */
7838.LOP_INSTANCE_OF_trivial:
7839    mov     r0, #1                      @ indicate success
7840    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7841    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7842    SET_VREG(r0, r9)                    @ vA<- r0
7843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7844    GOTO_OPCODE(ip)                     @ jump to next instruction
7845
7846    /*
7847     * Resolution required.  This is the least-likely path.
7848     *
7849     *  r3 holds BBBB
7850     *  r9 holds A
7851     */
7852.LOP_INSTANCE_OF_resolve:
7853    EXPORT_PC()                         @ resolve() could throw
7854    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7855    mov     r1, r3                      @ r1<- BBBB
7856    mov     r2, #1                      @ r2<- true
7857    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7858    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7859    cmp     r0, #0                      @ got null?
7860    beq     common_exceptionThrown      @ yes, handle exception
7861    mov     r1, r0                      @ r1<- class resolved from BBB
7862    mov     r3, rINST, lsr #12          @ r3<- B
7863    GET_VREG(r0, r3)                    @ r0<- vB (object)
7864    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7865    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7866
7867
7868/* continuation for OP_NEW_INSTANCE */
7869
7870    .balign 32                          @ minimize cache lines
7871.LOP_NEW_INSTANCE_finish: @ r0=new object
7872    mov     r3, rINST, lsr #8           @ r3<- AA
7873    cmp     r0, #0                      @ failed?
7874    beq     common_exceptionThrown      @ yes, handle the exception
7875    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7876    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7877    SET_VREG(r0, r3)                    @ vAA<- r0
7878    GOTO_OPCODE(ip)                     @ jump to next instruction
7879
7880    /*
7881     * Class initialization required.
7882     *
7883     *  r0 holds class object
7884     */
7885.LOP_NEW_INSTANCE_needinit:
7886    mov     r9, r0                      @ save r0
7887    bl      dvmInitClass                @ initialize class
7888    cmp     r0, #0                      @ check boolean result
7889    mov     r0, r9                      @ restore r0
7890    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7891    b       common_exceptionThrown      @ failed, deal with init exception
7892
7893    /*
7894     * Resolution required.  This is the least-likely path.
7895     *
7896     *  r1 holds BBBB
7897     */
7898.LOP_NEW_INSTANCE_resolve:
7899    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7900    mov     r2, #0                      @ r2<- false
7901    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7902    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7903    cmp     r0, #0                      @ got null?
7904    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7905    b       common_exceptionThrown      @ yes, handle exception
7906
7907.LstrInstantiationErrorPtr:
7908    .word   .LstrInstantiationError
7909
7910
7911/* continuation for OP_NEW_ARRAY */
7912
7913
7914    /*
7915     * Resolve class.  (This is an uncommon case.)
7916     *
7917     *  r1 holds array length
7918     *  r2 holds class ref CCCC
7919     */
7920.LOP_NEW_ARRAY_resolve:
7921    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7922    mov     r9, r1                      @ r9<- length (save)
7923    mov     r1, r2                      @ r1<- CCCC
7924    mov     r2, #0                      @ r2<- false
7925    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7926    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7927    cmp     r0, #0                      @ got null?
7928    mov     r1, r9                      @ r1<- length (restore)
7929    beq     common_exceptionThrown      @ yes, handle exception
7930    @ fall through to OP_NEW_ARRAY_finish
7931
7932    /*
7933     * Finish allocation.
7934     *
7935     *  r0 holds class
7936     *  r1 holds array length
7937     */
7938.LOP_NEW_ARRAY_finish:
7939    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7940    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7941    cmp     r0, #0                      @ failed?
7942    mov     r2, rINST, lsr #8           @ r2<- A+
7943    beq     common_exceptionThrown      @ yes, handle the exception
7944    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7945    and     r2, r2, #15                 @ r2<- A
7946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7947    SET_VREG(r0, r2)                    @ vA<- r0
7948    GOTO_OPCODE(ip)                     @ jump to next instruction
7949
7950
7951/* continuation for OP_FILLED_NEW_ARRAY */
7952
7953    /*
7954     * On entry:
7955     *  r0 holds array class
7956     *  r10 holds AA or BA
7957     */
7958.LOP_FILLED_NEW_ARRAY_continue:
7959    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7960    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7961    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7962    .if     0
7963    mov     r1, r10                     @ r1<- AA (length)
7964    .else
7965    mov     r1, r10, lsr #4             @ r1<- B (length)
7966    .endif
7967    cmp     r3, #'I'                    @ array of ints?
7968    cmpne   r3, #'L'                    @ array of objects?
7969    cmpne   r3, #'['                    @ array of arrays?
7970    mov     r9, r1                      @ save length in r9
7971    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7972    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7973    cmp     r0, #0                      @ null return?
7974    beq     common_exceptionThrown      @ alloc failed, handle exception
7975
7976    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7977    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7978    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7979    subs    r9, r9, #1                  @ length--, check for neg
7980    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7981    bmi     2f                          @ was zero, bail
7982
7983    @ copy values from registers into the array
7984    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7985    .if     0
7986    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79871:  ldr     r3, [r2], #4                @ r3<- *r2++
7988    subs    r9, r9, #1                  @ count--
7989    str     r3, [r0], #4                @ *contents++ = vX
7990    bpl     1b
7991    @ continue at 2
7992    .else
7993    cmp     r9, #4                      @ length was initially 5?
7994    and     r2, r10, #15                @ r2<- A
7995    bne     1f                          @ <= 4 args, branch
7996    GET_VREG(r3, r2)                    @ r3<- vA
7997    sub     r9, r9, #1                  @ count--
7998    str     r3, [r0, #16]               @ contents[4] = vA
79991:  and     r2, r1, #15                 @ r2<- F/E/D/C
8000    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8001    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8002    subs    r9, r9, #1                  @ count--
8003    str     r3, [r0], #4                @ *contents++ = vX
8004    bpl     1b
8005    @ continue at 2
8006    .endif
8007
80082:
8009    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8010    GOTO_OPCODE(ip)                     @ execute it
8011
8012    /*
8013     * Throw an exception indicating that we have not implemented this
8014     * mode of filled-new-array.
8015     */
8016.LOP_FILLED_NEW_ARRAY_notimpl:
8017    ldr     r0, .L_strInternalError
8018    ldr     r1, .L_strFilledNewArrayNotImpl
8019    bl      dvmThrowException
8020    b       common_exceptionThrown
8021
8022    .if     (!0)                 @ define in one or the other, not both
8023.L_strFilledNewArrayNotImpl:
8024    .word   .LstrFilledNewArrayNotImpl
8025.L_strInternalError:
8026    .word   .LstrInternalError
8027    .endif
8028
8029
8030/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8031
8032    /*
8033     * On entry:
8034     *  r0 holds array class
8035     *  r10 holds AA or BA
8036     */
8037.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8038    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8039    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8040    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8041    .if     1
8042    mov     r1, r10                     @ r1<- AA (length)
8043    .else
8044    mov     r1, r10, lsr #4             @ r1<- B (length)
8045    .endif
8046    cmp     r3, #'I'                    @ array of ints?
8047    cmpne   r3, #'L'                    @ array of objects?
8048    cmpne   r3, #'['                    @ array of arrays?
8049    mov     r9, r1                      @ save length in r9
8050    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8051    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8052    cmp     r0, #0                      @ null return?
8053    beq     common_exceptionThrown      @ alloc failed, handle exception
8054
8055    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8056    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8057    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8058    subs    r9, r9, #1                  @ length--, check for neg
8059    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8060    bmi     2f                          @ was zero, bail
8061
8062    @ copy values from registers into the array
8063    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8064    .if     1
8065    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80661:  ldr     r3, [r2], #4                @ r3<- *r2++
8067    subs    r9, r9, #1                  @ count--
8068    str     r3, [r0], #4                @ *contents++ = vX
8069    bpl     1b
8070    @ continue at 2
8071    .else
8072    cmp     r9, #4                      @ length was initially 5?
8073    and     r2, r10, #15                @ r2<- A
8074    bne     1f                          @ <= 4 args, branch
8075    GET_VREG(r3, r2)                    @ r3<- vA
8076    sub     r9, r9, #1                  @ count--
8077    str     r3, [r0, #16]               @ contents[4] = vA
80781:  and     r2, r1, #15                 @ r2<- F/E/D/C
8079    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8080    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8081    subs    r9, r9, #1                  @ count--
8082    str     r3, [r0], #4                @ *contents++ = vX
8083    bpl     1b
8084    @ continue at 2
8085    .endif
8086
80872:
8088    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8089    GOTO_OPCODE(ip)                     @ execute it
8090
8091    /*
8092     * Throw an exception indicating that we have not implemented this
8093     * mode of filled-new-array.
8094     */
8095.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8096    ldr     r0, .L_strInternalError
8097    ldr     r1, .L_strFilledNewArrayNotImpl
8098    bl      dvmThrowException
8099    b       common_exceptionThrown
8100
8101    .if     (!1)                 @ define in one or the other, not both
8102.L_strFilledNewArrayNotImpl:
8103    .word   .LstrFilledNewArrayNotImpl
8104.L_strInternalError:
8105    .word   .LstrInternalError
8106    .endif
8107
8108
8109/* continuation for OP_CMPL_FLOAT */
8110.LOP_CMPL_FLOAT_finish:
8111    SET_VREG(r0, r9)                    @ vAA<- r0
8112    GOTO_OPCODE(ip)                     @ jump to next instruction
8113
8114
8115/* continuation for OP_CMPG_FLOAT */
8116.LOP_CMPG_FLOAT_finish:
8117    SET_VREG(r0, r9)                    @ vAA<- r0
8118    GOTO_OPCODE(ip)                     @ jump to next instruction
8119
8120
8121/* continuation for OP_CMPL_DOUBLE */
8122.LOP_CMPL_DOUBLE_finish:
8123    SET_VREG(r0, r9)                    @ vAA<- r0
8124    GOTO_OPCODE(ip)                     @ jump to next instruction
8125
8126
8127/* continuation for OP_CMPG_DOUBLE */
8128.LOP_CMPG_DOUBLE_finish:
8129    SET_VREG(r0, r9)                    @ vAA<- r0
8130    GOTO_OPCODE(ip)                     @ jump to next instruction
8131
8132
8133/* continuation for OP_CMP_LONG */
8134
8135.LOP_CMP_LONG_less:
8136    mvn     r1, #0                      @ r1<- -1
8137    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8138    @ instead, we just replicate the tail end.
8139    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8140    SET_VREG(r1, r9)                    @ vAA<- r1
8141    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8142    GOTO_OPCODE(ip)                     @ jump to next instruction
8143
8144.LOP_CMP_LONG_greater:
8145    mov     r1, #1                      @ r1<- 1
8146    @ fall through to _finish
8147
8148.LOP_CMP_LONG_finish:
8149    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8150    SET_VREG(r1, r9)                    @ vAA<- r1
8151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8152    GOTO_OPCODE(ip)                     @ jump to next instruction
8153
8154
8155/* continuation for OP_AGET_WIDE */
8156
8157.LOP_AGET_WIDE_finish:
8158    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8159    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8160    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8162    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8163    GOTO_OPCODE(ip)                     @ jump to next instruction
8164
8165
8166/* continuation for OP_APUT_WIDE */
8167
8168.LOP_APUT_WIDE_finish:
8169    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8170    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8172    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8173    GOTO_OPCODE(ip)                     @ jump to next instruction
8174
8175
8176/* continuation for OP_APUT_OBJECT */
8177    /*
8178     * On entry:
8179     *  r1 = vBB (arrayObj)
8180     *  r9 = vAA (obj)
8181     *  r10 = offset into array (vBB + vCC * width)
8182     */
8183.LOP_APUT_OBJECT_finish:
8184    cmp     r9, #0                      @ storing null reference?
8185    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8186    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8187    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8188    bl      dvmCanPutArrayElement       @ test object type vs. array type
8189    cmp     r0, #0                      @ okay?
8190    beq     common_errArrayStore        @ no
8191.LOP_APUT_OBJECT_skip_check:
8192    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8194    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8195    GOTO_OPCODE(ip)                     @ jump to next instruction
8196
8197
8198/* continuation for OP_IGET */
8199
8200    /*
8201     * Currently:
8202     *  r0 holds resolved field
8203     *  r9 holds object
8204     */
8205.LOP_IGET_finish:
8206    @bl      common_squeak0
8207    cmp     r9, #0                      @ check object for null
8208    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8209    beq     common_errNullObject        @ object was null
8210    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8211    ubfx    r2, rINST, #8, #4           @ r2<- A
8212    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8213    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8214    SET_VREG(r0, r2)                    @ fp[A]<- r0
8215    GOTO_OPCODE(ip)                     @ jump to next instruction
8216
8217
8218/* continuation for OP_IGET_WIDE */
8219
8220    /*
8221     * Currently:
8222     *  r0 holds resolved field
8223     *  r9 holds object
8224     */
8225.LOP_IGET_WIDE_finish:
8226    cmp     r9, #0                      @ check object for null
8227    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8228    beq     common_errNullObject        @ object was null
8229    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8230    ubfx    r2, rINST, #8, #4           @ r2<- A
8231    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8232    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8234    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8235    GOTO_OPCODE(ip)                     @ jump to next instruction
8236
8237
8238/* continuation for OP_IGET_OBJECT */
8239
8240    /*
8241     * Currently:
8242     *  r0 holds resolved field
8243     *  r9 holds object
8244     */
8245.LOP_IGET_OBJECT_finish:
8246    @bl      common_squeak0
8247    cmp     r9, #0                      @ check object for null
8248    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8249    beq     common_errNullObject        @ object was null
8250    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8251    mov     r2, rINST, lsr #8           @ r2<- A+
8252    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8253    and     r2, r2, #15                 @ r2<- A
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
8259/* continuation for OP_IGET_BOOLEAN */
8260
8261    /*
8262     * Currently:
8263     *  r0 holds resolved field
8264     *  r9 holds object
8265     */
8266.LOP_IGET_BOOLEAN_finish:
8267    @bl      common_squeak1
8268    cmp     r9, #0                      @ check object for null
8269    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8270    beq     common_errNullObject        @ object was null
8271    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8272    mov     r2, rINST, lsr #8           @ r2<- A+
8273    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8274    and     r2, r2, #15                 @ r2<- A
8275    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8276    SET_VREG(r0, r2)                    @ fp[A]<- r0
8277    GOTO_OPCODE(ip)                     @ jump to next instruction
8278
8279
8280/* continuation for OP_IGET_BYTE */
8281
8282    /*
8283     * Currently:
8284     *  r0 holds resolved field
8285     *  r9 holds object
8286     */
8287.LOP_IGET_BYTE_finish:
8288    @bl      common_squeak2
8289    cmp     r9, #0                      @ check object for null
8290    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8291    beq     common_errNullObject        @ object was null
8292    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8293    mov     r2, rINST, lsr #8           @ r2<- A+
8294    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8295    and     r2, r2, #15                 @ r2<- A
8296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8297    SET_VREG(r0, r2)                    @ fp[A]<- r0
8298    GOTO_OPCODE(ip)                     @ jump to next instruction
8299
8300
8301/* continuation for OP_IGET_CHAR */
8302
8303    /*
8304     * Currently:
8305     *  r0 holds resolved field
8306     *  r9 holds object
8307     */
8308.LOP_IGET_CHAR_finish:
8309    @bl      common_squeak3
8310    cmp     r9, #0                      @ check object for null
8311    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8312    beq     common_errNullObject        @ object was null
8313    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8314    mov     r2, rINST, lsr #8           @ r2<- A+
8315    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8316    and     r2, r2, #15                 @ r2<- A
8317    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8318    SET_VREG(r0, r2)                    @ fp[A]<- r0
8319    GOTO_OPCODE(ip)                     @ jump to next instruction
8320
8321
8322/* continuation for OP_IGET_SHORT */
8323
8324    /*
8325     * Currently:
8326     *  r0 holds resolved field
8327     *  r9 holds object
8328     */
8329.LOP_IGET_SHORT_finish:
8330    @bl      common_squeak4
8331    cmp     r9, #0                      @ check object for null
8332    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8333    beq     common_errNullObject        @ object was null
8334    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8335    mov     r2, rINST, lsr #8           @ r2<- A+
8336    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8337    and     r2, r2, #15                 @ r2<- A
8338    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8339    SET_VREG(r0, r2)                    @ fp[A]<- r0
8340    GOTO_OPCODE(ip)                     @ jump to next instruction
8341
8342
8343/* continuation for OP_IPUT */
8344
8345    /*
8346     * Currently:
8347     *  r0 holds resolved field
8348     *  r9 holds object
8349     */
8350.LOP_IPUT_finish:
8351    @bl      common_squeak0
8352    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8353    ubfx    r1, rINST, #8, #4           @ r1<- A
8354    cmp     r9, #0                      @ check object for null
8355    GET_VREG(r0, r1)                    @ r0<- fp[A]
8356    beq     common_errNullObject        @ object was null
8357    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8358    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8359    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8360    GOTO_OPCODE(ip)                     @ jump to next instruction
8361
8362
8363/* continuation for OP_IPUT_WIDE */
8364
8365    /*
8366     * Currently:
8367     *  r0 holds resolved field
8368     *  r9 holds object
8369     */
8370.LOP_IPUT_WIDE_finish:
8371    ubfx    r2, rINST, #8, #4           @ r2<- A
8372    cmp     r9, #0                      @ check object for null
8373    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8374    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8375    beq     common_errNullObject        @ object was null
8376    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8377    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8379    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8380    GOTO_OPCODE(ip)                     @ jump to next instruction
8381
8382
8383/* continuation for OP_IPUT_OBJECT */
8384
8385    /*
8386     * Currently:
8387     *  r0 holds resolved field
8388     *  r9 holds object
8389     */
8390.LOP_IPUT_OBJECT_finish:
8391    @bl      common_squeak0
8392    mov     r1, rINST, lsr #8           @ r1<- A+
8393    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8394    and     r1, r1, #15                 @ r1<- A
8395    cmp     r9, #0                      @ check object for null
8396    GET_VREG(r0, r1)                    @ r0<- fp[A]
8397    beq     common_errNullObject        @ object was null
8398    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8399    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8400    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8401    GOTO_OPCODE(ip)                     @ jump to next instruction
8402
8403
8404/* continuation for OP_IPUT_BOOLEAN */
8405
8406    /*
8407     * Currently:
8408     *  r0 holds resolved field
8409     *  r9 holds object
8410     */
8411.LOP_IPUT_BOOLEAN_finish:
8412    @bl      common_squeak1
8413    mov     r1, rINST, lsr #8           @ r1<- A+
8414    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8415    and     r1, r1, #15                 @ r1<- A
8416    cmp     r9, #0                      @ check object for null
8417    GET_VREG(r0, r1)                    @ r0<- fp[A]
8418    beq     common_errNullObject        @ object was null
8419    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8420    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8421    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8422    GOTO_OPCODE(ip)                     @ jump to next instruction
8423
8424
8425/* continuation for OP_IPUT_BYTE */
8426
8427    /*
8428     * Currently:
8429     *  r0 holds resolved field
8430     *  r9 holds object
8431     */
8432.LOP_IPUT_BYTE_finish:
8433    @bl      common_squeak2
8434    mov     r1, rINST, lsr #8           @ r1<- A+
8435    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8436    and     r1, r1, #15                 @ r1<- A
8437    cmp     r9, #0                      @ check object for null
8438    GET_VREG(r0, r1)                    @ r0<- fp[A]
8439    beq     common_errNullObject        @ object was null
8440    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8442    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8443    GOTO_OPCODE(ip)                     @ jump to next instruction
8444
8445
8446/* continuation for OP_IPUT_CHAR */
8447
8448    /*
8449     * Currently:
8450     *  r0 holds resolved field
8451     *  r9 holds object
8452     */
8453.LOP_IPUT_CHAR_finish:
8454    @bl      common_squeak3
8455    mov     r1, rINST, lsr #8           @ r1<- A+
8456    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8457    and     r1, r1, #15                 @ r1<- A
8458    cmp     r9, #0                      @ check object for null
8459    GET_VREG(r0, r1)                    @ r0<- fp[A]
8460    beq     common_errNullObject        @ object was null
8461    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8462    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8463    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8464    GOTO_OPCODE(ip)                     @ jump to next instruction
8465
8466
8467/* continuation for OP_IPUT_SHORT */
8468
8469    /*
8470     * Currently:
8471     *  r0 holds resolved field
8472     *  r9 holds object
8473     */
8474.LOP_IPUT_SHORT_finish:
8475    @bl      common_squeak4
8476    mov     r1, rINST, lsr #8           @ r1<- A+
8477    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8478    and     r1, r1, #15                 @ r1<- A
8479    cmp     r9, #0                      @ check object for null
8480    GET_VREG(r0, r1)                    @ r0<- fp[A]
8481    beq     common_errNullObject        @ object was null
8482    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8483    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8484    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8485    GOTO_OPCODE(ip)                     @ jump to next instruction
8486
8487
8488/* continuation for OP_SGET */
8489
8490    /*
8491     * Continuation if the field has not yet been resolved.
8492     *  r1: BBBB field ref
8493     */
8494.LOP_SGET_resolve:
8495    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8496    EXPORT_PC()                         @ resolve() could throw, so export now
8497    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8498    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8499    cmp     r0, #0                      @ success?
8500    bne     .LOP_SGET_finish          @ yes, finish
8501    b       common_exceptionThrown      @ no, handle exception
8502
8503
8504/* continuation for OP_SGET_WIDE */
8505
8506    /*
8507     * Continuation if the field has not yet been resolved.
8508     *  r1: BBBB field ref
8509     *
8510     * Returns StaticField pointer in r0.
8511     */
8512.LOP_SGET_WIDE_resolve:
8513    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8514    EXPORT_PC()                         @ resolve() could throw, so export now
8515    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8516    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8517    cmp     r0, #0                      @ success?
8518    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8519    b       common_exceptionThrown      @ no, handle exception
8520
8521
8522/* continuation for OP_SGET_OBJECT */
8523
8524    /*
8525     * Continuation if the field has not yet been resolved.
8526     *  r1: BBBB field ref
8527     */
8528.LOP_SGET_OBJECT_resolve:
8529    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8530    EXPORT_PC()                         @ resolve() could throw, so export now
8531    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8532    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8533    cmp     r0, #0                      @ success?
8534    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8535    b       common_exceptionThrown      @ no, handle exception
8536
8537
8538/* continuation for OP_SGET_BOOLEAN */
8539
8540    /*
8541     * Continuation if the field has not yet been resolved.
8542     *  r1: BBBB field ref
8543     */
8544.LOP_SGET_BOOLEAN_resolve:
8545    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8546    EXPORT_PC()                         @ resolve() could throw, so export now
8547    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8548    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8549    cmp     r0, #0                      @ success?
8550    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8551    b       common_exceptionThrown      @ no, handle exception
8552
8553
8554/* continuation for OP_SGET_BYTE */
8555
8556    /*
8557     * Continuation if the field has not yet been resolved.
8558     *  r1: BBBB field ref
8559     */
8560.LOP_SGET_BYTE_resolve:
8561    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8562    EXPORT_PC()                         @ resolve() could throw, so export now
8563    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8564    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8565    cmp     r0, #0                      @ success?
8566    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8567    b       common_exceptionThrown      @ no, handle exception
8568
8569
8570/* continuation for OP_SGET_CHAR */
8571
8572    /*
8573     * Continuation if the field has not yet been resolved.
8574     *  r1: BBBB field ref
8575     */
8576.LOP_SGET_CHAR_resolve:
8577    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8578    EXPORT_PC()                         @ resolve() could throw, so export now
8579    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8580    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8581    cmp     r0, #0                      @ success?
8582    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8583    b       common_exceptionThrown      @ no, handle exception
8584
8585
8586/* continuation for OP_SGET_SHORT */
8587
8588    /*
8589     * Continuation if the field has not yet been resolved.
8590     *  r1: BBBB field ref
8591     */
8592.LOP_SGET_SHORT_resolve:
8593    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8594    EXPORT_PC()                         @ resolve() could throw, so export now
8595    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8596    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8597    cmp     r0, #0                      @ success?
8598    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8599    b       common_exceptionThrown      @ no, handle exception
8600
8601
8602/* continuation for OP_SPUT */
8603
8604    /*
8605     * Continuation if the field has not yet been resolved.
8606     *  r1: BBBB field ref
8607     */
8608.LOP_SPUT_resolve:
8609    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8610    EXPORT_PC()                         @ resolve() could throw, so export now
8611    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8612    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8613    cmp     r0, #0                      @ success?
8614    bne     .LOP_SPUT_finish          @ yes, finish
8615    b       common_exceptionThrown      @ no, handle exception
8616
8617
8618/* continuation for OP_SPUT_WIDE */
8619
8620    /*
8621     * Continuation if the field has not yet been resolved.
8622     *  r1: BBBB field ref
8623     *  r9: &fp[AA]
8624     *
8625     * Returns StaticField pointer in r2.
8626     */
8627.LOP_SPUT_WIDE_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    mov     r2, r0                      @ copy to r2
8634    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8635    b       common_exceptionThrown      @ no, handle exception
8636
8637
8638/* continuation for OP_SPUT_OBJECT */
8639
8640    /*
8641     * Continuation if the field has not yet been resolved.
8642     *  r1: BBBB field ref
8643     */
8644.LOP_SPUT_OBJECT_resolve:
8645    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8646    EXPORT_PC()                         @ resolve() could throw, so export now
8647    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8648    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8649    cmp     r0, #0                      @ success?
8650    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8651    b       common_exceptionThrown      @ no, handle exception
8652
8653
8654/* continuation for OP_SPUT_BOOLEAN */
8655
8656    /*
8657     * Continuation if the field has not yet been resolved.
8658     *  r1: BBBB field ref
8659     */
8660.LOP_SPUT_BOOLEAN_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    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8667    b       common_exceptionThrown      @ no, handle exception
8668
8669
8670/* continuation for OP_SPUT_BYTE */
8671
8672    /*
8673     * Continuation if the field has not yet been resolved.
8674     *  r1: BBBB field ref
8675     */
8676.LOP_SPUT_BYTE_resolve:
8677    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8678    EXPORT_PC()                         @ resolve() could throw, so export now
8679    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8680    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8681    cmp     r0, #0                      @ success?
8682    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8683    b       common_exceptionThrown      @ no, handle exception
8684
8685
8686/* continuation for OP_SPUT_CHAR */
8687
8688    /*
8689     * Continuation if the field has not yet been resolved.
8690     *  r1: BBBB field ref
8691     */
8692.LOP_SPUT_CHAR_resolve:
8693    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8694    EXPORT_PC()                         @ resolve() could throw, so export now
8695    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8696    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8697    cmp     r0, #0                      @ success?
8698    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8699    b       common_exceptionThrown      @ no, handle exception
8700
8701
8702/* continuation for OP_SPUT_SHORT */
8703
8704    /*
8705     * Continuation if the field has not yet been resolved.
8706     *  r1: BBBB field ref
8707     */
8708.LOP_SPUT_SHORT_resolve:
8709    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8710    EXPORT_PC()                         @ resolve() could throw, so export now
8711    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8712    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8713    cmp     r0, #0                      @ success?
8714    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8715    b       common_exceptionThrown      @ no, handle exception
8716
8717
8718/* continuation for OP_INVOKE_VIRTUAL */
8719
8720    /*
8721     * At this point:
8722     *  r0 = resolved base method
8723     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8724     */
8725.LOP_INVOKE_VIRTUAL_continue:
8726    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8727    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8728    cmp     r1, #0                      @ is "this" null?
8729    beq     common_errNullObject        @ null "this", throw exception
8730    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8731    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8732    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8733    bl      common_invokeMethodNoRange @ continue on
8734
8735
8736/* continuation for OP_INVOKE_SUPER */
8737
8738    /*
8739     * At this point:
8740     *  r0 = resolved base method
8741     *  r9 = method->clazz
8742     */
8743.LOP_INVOKE_SUPER_continue:
8744    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8745    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8746    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8747    EXPORT_PC()                         @ must export for invoke
8748    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8749    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8750    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8751    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8752    bl      common_invokeMethodNoRange @ continue on
8753
8754.LOP_INVOKE_SUPER_resolve:
8755    mov     r0, r9                      @ r0<- method->clazz
8756    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8757    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8758    cmp     r0, #0                      @ got null?
8759    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8760    b       common_exceptionThrown      @ yes, handle exception
8761
8762    /*
8763     * Throw a NoSuchMethodError with the method name as the message.
8764     *  r0 = resolved base method
8765     */
8766.LOP_INVOKE_SUPER_nsm:
8767    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8768    b       common_errNoSuchMethod
8769
8770
8771/* continuation for OP_INVOKE_DIRECT */
8772
8773    /*
8774     * On entry:
8775     *  r1 = reference (BBBB or CCCC)
8776     *  r10 = "this" register
8777     */
8778.LOP_INVOKE_DIRECT_resolve:
8779    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8780    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8781    mov     r2, #METHOD_DIRECT          @ resolver method type
8782    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8783    cmp     r0, #0                      @ got null?
8784    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8785    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8786    b       common_exceptionThrown      @ yes, handle exception
8787
8788
8789/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8790
8791    /*
8792     * At this point:
8793     *  r0 = resolved base method
8794     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8795     */
8796.LOP_INVOKE_VIRTUAL_RANGE_continue:
8797    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8798    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8799    cmp     r1, #0                      @ is "this" null?
8800    beq     common_errNullObject        @ null "this", throw exception
8801    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8802    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8803    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8804    bl      common_invokeMethodRange @ continue on
8805
8806
8807/* continuation for OP_INVOKE_SUPER_RANGE */
8808
8809    /*
8810     * At this point:
8811     *  r0 = resolved base method
8812     *  r9 = method->clazz
8813     */
8814.LOP_INVOKE_SUPER_RANGE_continue:
8815    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8816    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8817    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8818    EXPORT_PC()                         @ must export for invoke
8819    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8820    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8821    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8822    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8823    bl      common_invokeMethodRange @ continue on
8824
8825.LOP_INVOKE_SUPER_RANGE_resolve:
8826    mov     r0, r9                      @ r0<- method->clazz
8827    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8828    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8829    cmp     r0, #0                      @ got null?
8830    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8831    b       common_exceptionThrown      @ yes, handle exception
8832
8833    /*
8834     * Throw a NoSuchMethodError with the method name as the message.
8835     *  r0 = resolved base method
8836     */
8837.LOP_INVOKE_SUPER_RANGE_nsm:
8838    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8839    b       common_errNoSuchMethod
8840
8841
8842/* continuation for OP_INVOKE_DIRECT_RANGE */
8843
8844    /*
8845     * On entry:
8846     *  r1 = reference (BBBB or CCCC)
8847     *  r10 = "this" register
8848     */
8849.LOP_INVOKE_DIRECT_RANGE_resolve:
8850    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8851    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8852    mov     r2, #METHOD_DIRECT          @ resolver method type
8853    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8854    cmp     r0, #0                      @ got null?
8855    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8856    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8857    b       common_exceptionThrown      @ yes, handle exception
8858
8859
8860/* continuation for OP_FLOAT_TO_LONG */
8861/*
8862 * Convert the float in r0 to a long in r0/r1.
8863 *
8864 * We have to clip values to long min/max per the specification.  The
8865 * expected common case is a "reasonable" value that converts directly
8866 * to modest integer.  The EABI convert function isn't doing this for us.
8867 */
8868f2l_doconv:
8869    stmfd   sp!, {r4, lr}
8870    mov     r1, #0x5f000000             @ (float)maxlong
8871    mov     r4, r0
8872    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8873    cmp     r0, #0                      @ nonzero == yes
8874    mvnne   r0, #0                      @ return maxlong (7fffffff)
8875    mvnne   r1, #0x80000000
8876    ldmnefd sp!, {r4, pc}
8877
8878    mov     r0, r4                      @ recover arg
8879    mov     r1, #0xdf000000             @ (float)minlong
8880    bl      __aeabi_fcmple              @ is arg <= minlong?
8881    cmp     r0, #0                      @ nonzero == yes
8882    movne   r0, #0                      @ return minlong (80000000)
8883    movne   r1, #0x80000000
8884    ldmnefd sp!, {r4, pc}
8885
8886    mov     r0, r4                      @ recover arg
8887    mov     r1, r4
8888    bl      __aeabi_fcmpeq              @ is arg == self?
8889    cmp     r0, #0                      @ zero == no
8890    moveq   r1, #0                      @ return zero for NaN
8891    ldmeqfd sp!, {r4, pc}
8892
8893    mov     r0, r4                      @ recover arg
8894    bl      __aeabi_f2lz                @ convert float to long
8895    ldmfd   sp!, {r4, pc}
8896
8897
8898/* continuation for OP_DOUBLE_TO_LONG */
8899/*
8900 * Convert the double in r0/r1 to a long in r0/r1.
8901 *
8902 * We have to clip values to long min/max per the specification.  The
8903 * expected common case is a "reasonable" value that converts directly
8904 * to modest integer.  The EABI convert function isn't doing this for us.
8905 */
8906d2l_doconv:
8907    stmfd   sp!, {r4, r5, lr}           @ save regs
8908    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8909    add     r3, #0x00e00000             @  0x43e00000
8910    mov     r2, #0                      @ maxlong, as a double (low word)
8911    sub     sp, sp, #4                  @ align for EABI
8912    mov     r4, r0                      @ save a copy of r0
8913    mov     r5, r1                      @  and r1
8914    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8915    cmp     r0, #0                      @ nonzero == yes
8916    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8917    mvnne   r1, #0x80000000
8918    bne     1f
8919
8920    mov     r0, r4                      @ recover arg
8921    mov     r1, r5
8922    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8923    add     r3, #0x00e00000             @  0xc3e00000
8924    mov     r2, #0                      @ minlong, as a double (low word)
8925    bl      __aeabi_dcmple              @ is arg <= minlong?
8926    cmp     r0, #0                      @ nonzero == yes
8927    movne   r0, #0                      @ return minlong (8000000000000000)
8928    movne   r1, #0x80000000
8929    bne     1f
8930
8931    mov     r0, r4                      @ recover arg
8932    mov     r1, r5
8933    mov     r2, r4                      @ compare against self
8934    mov     r3, r5
8935    bl      __aeabi_dcmpeq              @ is arg == self?
8936    cmp     r0, #0                      @ zero == no
8937    moveq   r1, #0                      @ return zero for NaN
8938    beq     1f
8939
8940    mov     r0, r4                      @ recover arg
8941    mov     r1, r5
8942    bl      __aeabi_d2lz                @ convert double to long
8943
89441:
8945    add     sp, sp, #4
8946    ldmfd   sp!, {r4, r5, pc}
8947
8948
8949/* continuation for OP_MUL_LONG */
8950
8951.LOP_MUL_LONG_finish:
8952    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8953    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8954    GOTO_OPCODE(ip)                     @ jump to next instruction
8955
8956
8957/* continuation for OP_SHL_LONG */
8958
8959.LOP_SHL_LONG_finish:
8960    mov     r0, r0, asl r2              @  r0<- r0 << r2
8961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8962    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8963    GOTO_OPCODE(ip)                     @ jump to next instruction
8964
8965
8966/* continuation for OP_SHR_LONG */
8967
8968.LOP_SHR_LONG_finish:
8969    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8970    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8971    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8972    GOTO_OPCODE(ip)                     @ jump to next instruction
8973
8974
8975/* continuation for OP_USHR_LONG */
8976
8977.LOP_USHR_LONG_finish:
8978    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8980    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8981    GOTO_OPCODE(ip)                     @ jump to next instruction
8982
8983
8984/* continuation for OP_SHL_LONG_2ADDR */
8985
8986.LOP_SHL_LONG_2ADDR_finish:
8987    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8988    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8989    GOTO_OPCODE(ip)                     @ jump to next instruction
8990
8991
8992/* continuation for OP_SHR_LONG_2ADDR */
8993
8994.LOP_SHR_LONG_2ADDR_finish:
8995    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8996    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8997    GOTO_OPCODE(ip)                     @ jump to next instruction
8998
8999
9000/* continuation for OP_USHR_LONG_2ADDR */
9001
9002.LOP_USHR_LONG_2ADDR_finish:
9003    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9004    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9005    GOTO_OPCODE(ip)                     @ jump to next instruction
9006
9007
9008/* continuation for OP_IGET_WIDE_VOLATILE */
9009
9010    /*
9011     * Currently:
9012     *  r0 holds resolved field
9013     *  r9 holds object
9014     */
9015.LOP_IGET_WIDE_VOLATILE_finish:
9016    cmp     r9, #0                      @ check object for null
9017    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9018    beq     common_errNullObject        @ object was null
9019    .if 1
9020    add     r0, r9, r3                  @ r0<- address of field
9021    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
9022    .else
9023    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9024    .endif
9025    mov     r2, rINST, lsr #8           @ r2<- A+
9026    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9027    and     r2, r2, #15                 @ r2<- A
9028    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9030    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9031    GOTO_OPCODE(ip)                     @ jump to next instruction
9032
9033
9034/* continuation for OP_IPUT_WIDE_VOLATILE */
9035
9036    /*
9037     * Currently:
9038     *  r0 holds resolved field
9039     *  r9 holds object
9040     */
9041.LOP_IPUT_WIDE_VOLATILE_finish:
9042    mov     r2, rINST, lsr #8           @ r2<- A+
9043    cmp     r9, #0                      @ check object for null
9044    and     r2, r2, #15                 @ r2<- A
9045    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9046    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9047    beq     common_errNullObject        @ object was null
9048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9049    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9050    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9051    .if 1
9052    add     r2, r9, r3                  @ r2<- target address
9053    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
9054    .else
9055    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9056    .endif
9057    GOTO_OPCODE(r10)                    @ jump to next instruction
9058
9059
9060/* continuation for OP_SGET_WIDE_VOLATILE */
9061
9062    /*
9063     * Continuation if the field has not yet been resolved.
9064     *  r1: BBBB field ref
9065     *
9066     * Returns StaticField pointer in r0.
9067     */
9068.LOP_SGET_WIDE_VOLATILE_resolve:
9069    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9070    EXPORT_PC()                         @ resolve() could throw, so export now
9071    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9072    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9073    cmp     r0, #0                      @ success?
9074    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9075    b       common_exceptionThrown      @ no, handle exception
9076
9077
9078/* continuation for OP_SPUT_WIDE_VOLATILE */
9079
9080    /*
9081     * Continuation if the field has not yet been resolved.
9082     *  r1: BBBB field ref
9083     *  r9: &fp[AA]
9084     *
9085     * Returns StaticField pointer in r2.
9086     */
9087.LOP_SPUT_WIDE_VOLATILE_resolve:
9088    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9089    EXPORT_PC()                         @ resolve() could throw, so export now
9090    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9091    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9092    cmp     r0, #0                      @ success?
9093    mov     r2, r0                      @ copy to r2
9094    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9095    b       common_exceptionThrown      @ no, handle exception
9096
9097
9098/* continuation for OP_EXECUTE_INLINE */
9099
9100    /*
9101     * Extract args, call function.
9102     *  r0 = #of args (0-4)
9103     *  r10 = call index
9104     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9105     *
9106     * Other ideas:
9107     * - Use a jump table from the main piece to jump directly into the
9108     *   AND/LDR pairs.  Costs a data load, saves a branch.
9109     * - Have five separate pieces that do the loading, so we can work the
9110     *   interleave a little better.  Increases code size.
9111     */
9112.LOP_EXECUTE_INLINE_continue:
9113    rsb     r0, r0, #4                  @ r0<- 4-r0
9114    FETCH(r9, 2)                        @ r9<- FEDC
9115    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9116    bl      common_abort                @ (skipped due to ARM prefetch)
91174:  and     ip, r9, #0xf000             @ isolate F
9118    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
91193:  and     ip, r9, #0x0f00             @ isolate E
9120    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
91212:  and     ip, r9, #0x00f0             @ isolate D
9122    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
91231:  and     ip, r9, #0x000f             @ isolate C
9124    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
91250:
9126    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9127    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9128    @ (not reached)
9129
9130.LOP_EXECUTE_INLINE_table:
9131    .word   gDvmInlineOpsTable
9132
9133
9134/* continuation for OP_EXECUTE_INLINE_RANGE */
9135
9136    /*
9137     * Extract args, call function.
9138     *  r0 = #of args (0-4)
9139     *  r10 = call index
9140     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9141     */
9142.LOP_EXECUTE_INLINE_RANGE_continue:
9143    rsb     r0, r0, #4                  @ r0<- 4-r0
9144    FETCH(r9, 2)                        @ r9<- CCCC
9145    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9146    bl      common_abort                @ (skipped due to ARM prefetch)
91474:  add     ip, r9, #3                  @ base+3
9148    GET_VREG(r3, ip)                    @ r3<- vBase[3]
91493:  add     ip, r9, #2                  @ base+2
9150    GET_VREG(r2, ip)                    @ r2<- vBase[2]
91512:  add     ip, r9, #1                  @ base+1
9152    GET_VREG(r1, ip)                    @ r1<- vBase[1]
91531:  add     ip, r9, #0                  @ (nop)
9154    GET_VREG(r0, ip)                    @ r0<- vBase[0]
91550:
9156    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9157    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9158    @ (not reached)
9159
9160.LOP_EXECUTE_INLINE_RANGE_table:
9161    .word   gDvmInlineOpsTable
9162
9163
9164    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9165    .global dvmAsmSisterEnd
9166dvmAsmSisterEnd:
9167
9168/* File: armv5te/footer.S */
9169
9170/*
9171 * ===========================================================================
9172 *  Common subroutines and data
9173 * ===========================================================================
9174 */
9175
9176
9177
9178    .text
9179    .align  2
9180
9181#if defined(WITH_JIT)
9182#if defined(WITH_SELF_VERIFICATION)
9183    .global dvmJitToInterpPunt
9184dvmJitToInterpPunt:
9185    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9186    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9187    mov    r3, #0
9188    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9189    b      jitSVShadowRunEnd            @ doesn't return
9190
9191    .global dvmJitToInterpSingleStep
9192dvmJitToInterpSingleStep:
9193    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9194    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9195    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9196    b      jitSVShadowRunEnd            @ doesn't return
9197
9198    .global dvmJitToInterpTraceSelectNoChain
9199dvmJitToInterpTraceSelectNoChain:
9200    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9201    mov    r0,rPC                       @ pass our target PC
9202    mov    r2,#kSVSTraceSelectNoChain   @ r2<- interpreter entry point
9203    mov    r3, #0
9204    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9205    b      jitSVShadowRunEnd            @ doesn't return
9206
9207    .global dvmJitToInterpTraceSelect
9208dvmJitToInterpTraceSelect:
9209    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9210    ldr    r0,[lr, #-1]                 @ pass our target PC
9211    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9212    mov    r3, #0
9213    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9214    b      jitSVShadowRunEnd            @ doesn't return
9215
9216    .global dvmJitToInterpBackwardBranch
9217dvmJitToInterpBackwardBranch:
9218    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9219    ldr    r0,[lr, #-1]                 @ pass our target PC
9220    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9221    mov    r3, #0
9222    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9223    b      jitSVShadowRunEnd            @ doesn't return
9224
9225    .global dvmJitToInterpNormal
9226dvmJitToInterpNormal:
9227    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9228    ldr    r0,[lr, #-1]                 @ pass our target PC
9229    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9230    mov    r3, #0
9231    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9232    b      jitSVShadowRunEnd            @ doesn't return
9233
9234    .global dvmJitToInterpNoChain
9235dvmJitToInterpNoChain:
9236    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9237    mov    r0,rPC                       @ pass our target PC
9238    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9239    mov    r3, #0
9240    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9241    b      jitSVShadowRunEnd            @ doesn't return
9242#else
9243/*
9244 * Return from the translation cache to the interpreter when the compiler is
9245 * having issues translating/executing a Dalvik instruction. We have to skip
9246 * the code cache lookup otherwise it is possible to indefinitely bouce
9247 * between the interpreter and the code cache if the instruction that fails
9248 * to be compiled happens to be at a trace start.
9249 */
9250    .global dvmJitToInterpPunt
9251dvmJitToInterpPunt:
9252    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9253    mov    rPC, r0
9254#ifdef JIT_STATS
9255    mov    r0,lr
9256    bl     dvmBumpPunt;
9257#endif
9258    EXPORT_PC()
9259    mov    r0, #0
9260    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9261    adrl   rIBASE, dvmAsmInstructionStart
9262    FETCH_INST()
9263    GET_INST_OPCODE(ip)
9264    GOTO_OPCODE(ip)
9265
9266/*
9267 * Return to the interpreter to handle a single instruction.
9268 * On entry:
9269 *    r0 <= PC
9270 *    r1 <= PC of resume instruction
9271 *    lr <= resume point in translation
9272 */
9273    .global dvmJitToInterpSingleStep
9274dvmJitToInterpSingleStep:
9275    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9276    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9277    mov    r1,#kInterpEntryInstr
9278    @ enum is 4 byte in aapcs-EABI
9279    str    r1, [rGLUE, #offGlue_entryPoint]
9280    mov    rPC,r0
9281    EXPORT_PC()
9282
9283    adrl   rIBASE, dvmAsmInstructionStart
9284    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9285    str    r2,[rGLUE,#offGlue_jitState]
9286    mov    r1,#1                  @ set changeInterp to bail to debug interp
9287    b      common_gotoBail
9288
9289/*
9290 * Return from the translation cache and immediately request
9291 * a translation for the exit target.  Commonly used for callees.
9292 */
9293    .global dvmJitToInterpTraceSelectNoChain
9294dvmJitToInterpTraceSelectNoChain:
9295#ifdef JIT_STATS
9296    bl     dvmBumpNoChain
9297#endif
9298    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9299    mov    r0,rPC
9300    bl     dvmJitGetCodeAddr        @ Is there a translation?
9301    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9302    mov    r1, rPC                  @ arg1 of translation may need this
9303    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9304    cmp    r0,#0
9305    bxne   r0                       @ continue native execution if so
9306    b      2f
9307
9308/*
9309 * Return from the translation cache and immediately request
9310 * a translation for the exit target.  Commonly used following
9311 * invokes.
9312 */
9313    .global dvmJitToInterpTraceSelect
9314dvmJitToInterpTraceSelect:
9315    ldr    rPC,[lr, #-1]           @ get our target PC
9316    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9317    add    rINST,lr,#-5            @ save start of chain branch
9318    mov    r0,rPC
9319    bl     dvmJitGetCodeAddr       @ Is there a translation?
9320    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9321    cmp    r0,#0
9322    beq    2f
9323    mov    r1,rINST
9324    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9325    mov    r1, rPC                  @ arg1 of translation may need this
9326    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9327    cmp    r0,#0                    @ successful chain?
9328    bxne   r0                       @ continue native execution
9329    b      toInterpreter            @ didn't chain - resume with interpreter
9330
9331/* No translation, so request one if profiling isn't disabled*/
93322:
9333    adrl   rIBASE, dvmAsmInstructionStart
9334    GET_JIT_PROF_TABLE(r0)
9335    FETCH_INST()
9336    cmp    r0, #0
9337    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9338    bne    common_selectTrace
9339    GET_INST_OPCODE(ip)
9340    GOTO_OPCODE(ip)
9341
9342/*
9343 * Return from the translation cache to the interpreter.
9344 * The return was done with a BLX from thumb mode, and
9345 * the following 32-bit word contains the target rPC value.
9346 * Note that lr (r14) will have its low-order bit set to denote
9347 * its thumb-mode origin.
9348 *
9349 * We'll need to stash our lr origin away, recover the new
9350 * target and then check to see if there is a translation available
9351 * for our new target.  If so, we do a translation chain and
9352 * go back to native execution.  Otherwise, it's back to the
9353 * interpreter (after treating this entry as a potential
9354 * trace start).
9355 */
9356    .global dvmJitToInterpNormal
9357dvmJitToInterpNormal:
9358    ldr    rPC,[lr, #-1]           @ get our target PC
9359    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9360    add    rINST,lr,#-5            @ save start of chain branch
9361#ifdef JIT_STATS
9362    bl     dvmBumpNormal
9363#endif
9364    mov    r0,rPC
9365    bl     dvmJitGetCodeAddr        @ Is there a translation?
9366    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9367    cmp    r0,#0
9368    beq    toInterpreter            @ go if not, otherwise do chain
9369    mov    r1,rINST
9370    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9371    mov    r1, rPC                  @ arg1 of translation may need this
9372    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9373    cmp    r0,#0                    @ successful chain?
9374    bxne   r0                       @ continue native execution
9375    b      toInterpreter            @ didn't chain - resume with interpreter
9376
9377/*
9378 * Return from the translation cache to the interpreter to do method invocation.
9379 * Check if translation exists for the callee, but don't chain to it.
9380 */
9381    .global dvmJitToInterpNoChain
9382dvmJitToInterpNoChain:
9383#ifdef JIT_STATS
9384    bl     dvmBumpNoChain
9385#endif
9386    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9387    mov    r0,rPC
9388    bl     dvmJitGetCodeAddr        @ Is there a translation?
9389    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9390    mov    r1, rPC                  @ arg1 of translation may need this
9391    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9392    cmp    r0,#0
9393    bxne   r0                       @ continue native execution if so
9394#endif
9395
9396/*
9397 * No translation, restore interpreter regs and start interpreting.
9398 * rGLUE & rFP were preserved in the translated code, and rPC has
9399 * already been restored by the time we get here.  We'll need to set
9400 * up rIBASE & rINST, and load the address of the JitTable into r0.
9401 */
9402toInterpreter:
9403    EXPORT_PC()
9404    adrl   rIBASE, dvmAsmInstructionStart
9405    FETCH_INST()
9406    GET_JIT_PROF_TABLE(r0)
9407    @ NOTE: intended fallthrough
9408/*
9409 * Common code to update potential trace start counter, and initiate
9410 * a trace-build if appropriate.  On entry, rPC should point to the
9411 * next instruction to execute, and rINST should be already loaded with
9412 * the next opcode word, and r0 holds a pointer to the jit profile
9413 * table (pJitProfTable).
9414 */
9415common_testUpdateProfile:
9416    cmp     r0,#0
9417    GET_INST_OPCODE(ip)
9418    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9419
9420common_updateProfile:
9421    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9422    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9423    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9424    GET_INST_OPCODE(ip)
9425    subs    r1,r1,#1           @ decrement counter
9426    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9427    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9428
9429/*
9430 * Here, we switch to the debug interpreter to request
9431 * trace selection.  First, though, check to see if there
9432 * is already a native translation in place (and, if so,
9433 * jump to it now).
9434 */
9435    GET_JIT_THRESHOLD(r1)
9436    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9437    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9438    EXPORT_PC()
9439    mov     r0,rPC
9440    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9441    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9442    mov     r1, rPC                     @ arg1 of translation may need this
9443    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9444    cmp     r0,#0
9445#if !defined(WITH_SELF_VERIFICATION)
9446    bxne    r0                          @ jump to the translation
9447    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9448    @ fall-through to common_selectTrace
9449#else
9450    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9451    beq     common_selectTrace
9452    /*
9453     * At this point, we have a target translation.  However, if
9454     * that translation is actually the interpret-only pseudo-translation
9455     * we want to treat it the same as no translation.
9456     */
9457    mov     r10, r0                     @ save target
9458    bl      dvmCompilerGetInterpretTemplate
9459    cmp     r0, r10                     @ special case?
9460    bne     jitSVShadowRunStart         @ set up self verification shadow space
9461    GET_INST_OPCODE(ip)
9462    GOTO_OPCODE(ip)
9463    /* no return */
9464#endif
9465
9466/*
9467 * On entry:
9468 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9469 */
9470common_selectTrace:
9471    str     r2,[rGLUE,#offGlue_jitState]
9472    mov     r2,#kInterpEntryInstr       @ normal entry reason
9473    str     r2,[rGLUE,#offGlue_entryPoint]
9474    mov     r1,#1                       @ set changeInterp
9475    b       common_gotoBail
9476
9477#if defined(WITH_SELF_VERIFICATION)
9478/*
9479 * Save PC and registers to shadow memory for self verification mode
9480 * before jumping to native translation.
9481 * On entry:
9482 *    rPC, rFP, rGLUE: the values that they should contain
9483 *    r10: the address of the target translation.
9484 */
9485jitSVShadowRunStart:
9486    mov     r0,rPC                      @ r0<- program counter
9487    mov     r1,rFP                      @ r1<- frame pointer
9488    mov     r2,rGLUE                    @ r2<- InterpState pointer
9489    mov     r3,r10                      @ r3<- target translation
9490    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9491    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9492    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9493    bx      r10                         @ jump to the translation
9494
9495/*
9496 * Restore PC, registers, and interpState to original values
9497 * before jumping back to the interpreter.
9498 */
9499jitSVShadowRunEnd:
9500    mov    r1,rFP                        @ pass ending fp
9501    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9502    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9503    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9504    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9505    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9506    cmp    r1,#0                         @ check for punt condition
9507    beq    1f
9508    mov    r2,#kJitSelfVerification      @ ask for self verification
9509    str    r2,[rGLUE,#offGlue_jitState]
9510    mov    r2,#kInterpEntryInstr         @ normal entry reason
9511    str    r2,[rGLUE,#offGlue_entryPoint]
9512    mov    r1,#1                         @ set changeInterp
9513    b      common_gotoBail
9514
95151:                                       @ exit to interpreter without check
9516    EXPORT_PC()
9517    adrl   rIBASE, dvmAsmInstructionStart
9518    FETCH_INST()
9519    GET_INST_OPCODE(ip)
9520    GOTO_OPCODE(ip)
9521#endif
9522
9523#endif
9524
9525/*
9526 * Common code when a backward branch is taken.
9527 *
9528 * TODO: we could avoid a branch by just setting r0 and falling through
9529 * into the common_periodicChecks code, and having a test on r0 at the
9530 * end determine if we should return to the caller or update & branch to
9531 * the next instr.
9532 *
9533 * On entry:
9534 *  r9 is PC adjustment *in bytes*
9535 */
9536common_backwardBranch:
9537    mov     r0, #kInterpEntryInstr
9538    bl      common_periodicChecks
9539#if defined(WITH_JIT)
9540    GET_JIT_PROF_TABLE(r0)
9541    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9542    cmp     r0,#0
9543    bne     common_updateProfile
9544    GET_INST_OPCODE(ip)
9545    GOTO_OPCODE(ip)
9546#else
9547    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9549    GOTO_OPCODE(ip)                     @ jump to next instruction
9550#endif
9551
9552
9553/*
9554 * Need to see if the thread needs to be suspended or debugger/profiler
9555 * activity has begun.  If so, we suspend the thread or side-exit to
9556 * the debug interpreter as appropriate.
9557 *
9558 * The common case is no activity on any of these, so we want to figure
9559 * that out quickly.  If something is up, we can then sort out what.
9560 *
9561 * We want to be fast if the VM was built without debugger or profiler
9562 * support, but we also need to recognize that the system is usually
9563 * shipped with both of these enabled.
9564 *
9565 * TODO: reduce this so we're just checking a single location.
9566 *
9567 * On entry:
9568 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9569 *  r9 is trampoline PC adjustment *in bytes*
9570 */
9571common_periodicChecks:
9572    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9573
9574#if defined(WITH_DEBUGGER)
9575    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9576#endif
9577#if defined(WITH_PROFILER)
9578    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9579#endif
9580
9581    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9582
9583#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9584    cmp     r1, #0                      @ debugger enabled?
9585    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9586    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9587    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9588    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9589#elif defined(WITH_DEBUGGER)
9590    cmp     r1, #0                      @ debugger enabled?
9591    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9592    orrsne  ip, ip, r1                  @ yes, ip<- suspend | debugger; set Z
9593    @ (if not enabled, Z was set by test for r1==0, which is what we want)
9594#elif defined (WITH_PROFILER)
9595    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9596    orrs    ip, ip, r2                  @ ip<- suspendCount | activeProfilers
9597#else
9598    cmp     ip, #0                      @ not ORing anything in; set Z
9599#endif
9600
9601    bxeq    lr                          @ all zero, return
9602
9603    /*
9604     * One or more interesting events have happened.  Figure out what.
9605     *
9606     * If debugging or profiling are compiled in, we need to disambiguate.
9607     *
9608     * r0 still holds the reentry type.
9609     */
9610#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9611    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9612    cmp     ip, #0                      @ want suspend?
9613    beq     1f                          @ no, must be debugger/profiler
9614#endif
9615
9616    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9617#if defined(WITH_JIT)
9618    /*
9619     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9620     * doubles as the Jit's on/off switch.
9621     */
9622    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9623    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9624    ldr     r3, [r3] @ r3 <- pJitProfTable
9625    EXPORT_PC()                         @ need for precise GC
9626    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9627#else
9628    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9629    EXPORT_PC()                         @ need for precise GC
9630#endif
9631    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9632    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9633
9634#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9635
9636    /*
9637     * Reload the debugger/profiler enable flags.  We're checking to see
9638     * if either of these got set while we were suspended.
9639     *
9640     * We can't really avoid the #ifdefs here, because the fields don't
9641     * exist when the feature is disabled.
9642     */
9643#if defined(WITH_DEBUGGER)
9644    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9645    cmp     r1, #0                      @ debugger enabled?
9646    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9647#else
9648    mov     r1, #0
9649#endif
9650#if defined(WITH_PROFILER)
9651    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9652    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9653#else
9654    mov     r2, #0
9655#endif
9656
9657    orrs    r1, r1, r2
9658    beq     2f
9659
96601:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9661    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9662    add     rPC, rPC, r9                @ update rPC
9663    mov     r1, #1                      @ "want switch" = true
9664    b       common_gotoBail             @ side exit
9665
9666#endif /*WITH_DEBUGGER || WITH_PROFILER*/
9667
96682:
9669    bx      lr                          @ nothing to do, return
9670
9671
9672/*
9673 * The equivalent of "goto bail", this calls through the "bail handler".
9674 *
9675 * State registers will be saved to the "glue" area before bailing.
9676 *
9677 * On entry:
9678 *  r1 is "bool changeInterp", indicating if we want to switch to the
9679 *     other interpreter or just bail all the way out
9680 */
9681common_gotoBail:
9682    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9683    mov     r0, rGLUE                   @ r0<- glue ptr
9684    b       dvmMterpStdBail             @ call(glue, changeInterp)
9685
9686    @add     r1, r1, #1                  @ using (boolean+1)
9687    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9688    @bl      _longjmp                    @ does not return
9689    @bl      common_abort
9690
9691
9692/*
9693 * Common code for method invocation with range.
9694 *
9695 * On entry:
9696 *  r0 is "Method* methodToCall", the method we're trying to call
9697 */
9698common_invokeMethodRange:
9699.LinvokeNewRange:
9700    @ prepare to copy args to "outs" area of current frame
9701    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9702    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9703    beq     .LinvokeArgsDone            @ if no args, skip the rest
9704    FETCH(r1, 2)                        @ r1<- CCCC
9705
9706    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9707    @ (very few methods have > 10 args; could unroll for common cases)
9708    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9709    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9710    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
97111:  ldr     r1, [r3], #4                @ val = *fp++
9712    subs    r2, r2, #1                  @ count--
9713    str     r1, [r10], #4               @ *outs++ = val
9714    bne     1b                          @ ...while count != 0
9715    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9716    b       .LinvokeArgsDone
9717
9718/*
9719 * Common code for method invocation without range.
9720 *
9721 * On entry:
9722 *  r0 is "Method* methodToCall", the method we're trying to call
9723 */
9724common_invokeMethodNoRange:
9725.LinvokeNewNoRange:
9726    @ prepare to copy args to "outs" area of current frame
9727    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9728    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9729    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9730    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9731    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9732    beq     .LinvokeArgsDone
9733
9734    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9735.LinvokeNonRange:
9736    rsb     r2, r2, #5                  @ r2<- 5-r2
9737    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9738    bl      common_abort                @ (skipped due to ARM prefetch)
97395:  and     ip, rINST, #0x0f00          @ isolate A
9740    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9741    mov     r0, r0                      @ nop
9742    str     r2, [r10, #-4]!             @ *--outs = vA
97434:  and     ip, r1, #0xf000             @ isolate G
9744    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9745    mov     r0, r0                      @ nop
9746    str     r2, [r10, #-4]!             @ *--outs = vG
97473:  and     ip, r1, #0x0f00             @ isolate F
9748    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9749    mov     r0, r0                      @ nop
9750    str     r2, [r10, #-4]!             @ *--outs = vF
97512:  and     ip, r1, #0x00f0             @ isolate E
9752    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9753    mov     r0, r0                      @ nop
9754    str     r2, [r10, #-4]!             @ *--outs = vE
97551:  and     ip, r1, #0x000f             @ isolate D
9756    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9757    mov     r0, r0                      @ nop
9758    str     r2, [r10, #-4]!             @ *--outs = vD
97590:  @ fall through to .LinvokeArgsDone
9760
9761.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9762    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9763    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9764    @ find space for the new stack frame, check for overflow
9765    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9766    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9767    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9768@    bl      common_dumpRegs
9769    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9770    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9771    cmp     r3, r9                      @ bottom < interpStackEnd?
9772    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9773    blo     .LstackOverflow             @ yes, this frame will overflow stack
9774
9775    @ set up newSaveArea
9776#ifdef EASY_GDB
9777    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9778    str     ip, [r10, #offStackSaveArea_prevSave]
9779#endif
9780    str     rFP, [r10, #offStackSaveArea_prevFrame]
9781    str     rPC, [r10, #offStackSaveArea_savedPc]
9782#if defined(WITH_JIT)
9783    mov     r9, #0
9784    str     r9, [r10, #offStackSaveArea_returnAddr]
9785#endif
9786    str     r0, [r10, #offStackSaveArea_method]
9787    tst     r3, #ACC_NATIVE
9788    bne     .LinvokeNative
9789
9790    /*
9791    stmfd   sp!, {r0-r3}
9792    bl      common_printNewline
9793    mov     r0, rFP
9794    mov     r1, #0
9795    bl      dvmDumpFp
9796    ldmfd   sp!, {r0-r3}
9797    stmfd   sp!, {r0-r3}
9798    mov     r0, r1
9799    mov     r1, r10
9800    bl      dvmDumpFp
9801    bl      common_printNewline
9802    ldmfd   sp!, {r0-r3}
9803    */
9804
9805    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9806    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9807    mov     rPC, r2                         @ publish new rPC
9808    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9809
9810    @ Update "glue" values for the new method
9811    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9812    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9813    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9814#if defined(WITH_JIT)
9815    GET_JIT_PROF_TABLE(r0)
9816    mov     rFP, r1                         @ fp = newFp
9817    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9818    mov     rINST, r9                       @ publish new rINST
9819    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9820    cmp     r0,#0
9821    bne     common_updateProfile
9822    GOTO_OPCODE(ip)                         @ jump to next instruction
9823#else
9824    mov     rFP, r1                         @ fp = newFp
9825    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9826    mov     rINST, r9                       @ publish new rINST
9827    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9828    GOTO_OPCODE(ip)                         @ jump to next instruction
9829#endif
9830
9831.LinvokeNative:
9832    @ Prep for the native call
9833    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9834    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9835    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9836    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9837    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9838    mov     r9, r3                      @ r9<- glue->self (preserve)
9839
9840    mov     r2, r0                      @ r2<- methodToCall
9841    mov     r0, r1                      @ r0<- newFp (points to args)
9842    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9843
9844#ifdef ASSIST_DEBUGGER
9845    /* insert fake function header to help gdb find the stack frame */
9846    b       .Lskip
9847    .type   dalvik_mterp, %function
9848dalvik_mterp:
9849    .fnstart
9850    MTERP_ENTRY1
9851    MTERP_ENTRY2
9852.Lskip:
9853#endif
9854
9855    @mov     lr, pc                      @ set return addr
9856    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9857    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9858
9859#if defined(WITH_JIT)
9860    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9861#endif
9862
9863    @ native return; r9=self, r10=newSaveArea
9864    @ equivalent to dvmPopJniLocals
9865    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9866    ldr     r1, [r9, #offThread_exception] @ check for exception
9867#if defined(WITH_JIT)
9868    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9869#endif
9870    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9871    cmp     r1, #0                      @ null?
9872    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9873#if defined(WITH_JIT)
9874    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9875#endif
9876    bne     common_exceptionThrown      @ no, handle exception
9877
9878    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9880    GOTO_OPCODE(ip)                     @ jump to next instruction
9881
9882.LstackOverflow:    @ r0=methodToCall
9883    mov     r1, r0                      @ r1<- methodToCall
9884    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9885    bl      dvmHandleStackOverflow
9886    b       common_exceptionThrown
9887#ifdef ASSIST_DEBUGGER
9888    .fnend
9889#endif
9890
9891
9892    /*
9893     * Common code for method invocation, calling through "glue code".
9894     *
9895     * TODO: now that we have range and non-range invoke handlers, this
9896     *       needs to be split into two.  Maybe just create entry points
9897     *       that set r9 and jump here?
9898     *
9899     * On entry:
9900     *  r0 is "Method* methodToCall", the method we're trying to call
9901     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9902     */
9903     .if    0
9904.LinvokeOld:
9905    sub     sp, sp, #8                  @ space for args + pad
9906    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9907    mov     r2, r0                      @ A2<- methodToCall
9908    mov     r0, rGLUE                   @ A0<- glue
9909    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9910    mov     r1, r9                      @ A1<- methodCallRange
9911    mov     r3, rINST, lsr #8           @ A3<- AA
9912    str     ip, [sp, #0]                @ A4<- ip
9913    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9914    add     sp, sp, #8                  @ remove arg area
9915    b       common_resumeAfterGlueCall  @ continue to next instruction
9916    .endif
9917
9918
9919
9920/*
9921 * Common code for handling a return instruction.
9922 *
9923 * This does not return.
9924 */
9925common_returnFromMethod:
9926.LreturnNew:
9927    mov     r0, #kInterpEntryReturn
9928    mov     r9, #0
9929    bl      common_periodicChecks
9930
9931    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9932    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9933    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9934    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9935                                        @ r2<- method we're returning to
9936    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9937    cmp     r2, #0                      @ is this a break frame?
9938    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9939    mov     r1, #0                      @ "want switch" = false
9940    beq     common_gotoBail             @ break frame, bail out completely
9941
9942    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9943    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9944    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9945    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9946#if defined(WITH_JIT)
9947    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
9948    GET_JIT_PROF_TABLE(r0)
9949    mov     rPC, r9                     @ publish new rPC
9950    str     r1, [rGLUE, #offGlue_methodClassDex]
9951    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
9952    cmp     r10, #0                      @ caller is compiled code
9953    blxne   r10
9954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9955    cmp     r0,#0
9956    bne     common_updateProfile
9957    GOTO_OPCODE(ip)                     @ jump to next instruction
9958#else
9959    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9960    mov     rPC, r9                     @ publish new rPC
9961    str     r1, [rGLUE, #offGlue_methodClassDex]
9962    GOTO_OPCODE(ip)                     @ jump to next instruction
9963#endif
9964
9965    /*
9966     * Return handling, calls through "glue code".
9967     */
9968     .if    0
9969.LreturnOld:
9970    SAVE_PC_FP_TO_GLUE()                @ export state
9971    mov     r0, rGLUE                   @ arg to function
9972    bl      dvmMterp_returnFromMethod
9973    b       common_resumeAfterGlueCall
9974    .endif
9975
9976
9977/*
9978 * Somebody has thrown an exception.  Handle it.
9979 *
9980 * If the exception processing code returns to us (instead of falling
9981 * out of the interpreter), continue with whatever the next instruction
9982 * now happens to be.
9983 *
9984 * This does not return.
9985 */
9986     .global dvmMterpCommonExceptionThrown
9987dvmMterpCommonExceptionThrown:
9988common_exceptionThrown:
9989.LexceptionNew:
9990    mov     r0, #kInterpEntryThrow
9991    mov     r9, #0
9992    bl      common_periodicChecks
9993
9994    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9995    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9996    mov     r1, r10                     @ r1<- self
9997    mov     r0, r9                      @ r0<- exception
9998    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9999    mov     r3, #0                      @ r3<- NULL
10000    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10001
10002    /* set up args and a local for "&fp" */
10003    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10004    str     rFP, [sp, #-4]!             @ *--sp = fp
10005    mov     ip, sp                      @ ip<- &fp
10006    mov     r3, #0                      @ r3<- false
10007    str     ip, [sp, #-4]!              @ *--sp = &fp
10008    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10009    mov     r0, r10                     @ r0<- self
10010    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10011    mov     r2, r9                      @ r2<- exception
10012    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10013    mov     r1, r1, asr #1              @ r1<- offset in code units
10014
10015    /* call, r0 gets catchRelPc (a code-unit offset) */
10016    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10017
10018    /* fix earlier stack overflow if necessary; may trash rFP */
10019    ldrb    r1, [r10, #offThread_stackOverflowed]
10020    cmp     r1, #0                      @ did we overflow earlier?
10021    beq     1f                          @ no, skip ahead
10022    mov     rFP, r0                     @ save relPc result in rFP
10023    mov     r0, r10                     @ r0<- self
10024    mov     r1, r9                      @ r1<- exception
10025    bl      dvmCleanupStackOverflow     @ call(self)
10026    mov     r0, rFP                     @ restore result
100271:
10028
10029    /* update frame pointer and check result from dvmFindCatchBlock */
10030    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10031    cmp     r0, #0                      @ is catchRelPc < 0?
10032    add     sp, sp, #8                  @ restore stack
10033    bmi     .LnotCaughtLocally
10034
10035    /* adjust locals to match self->curFrame and updated PC */
10036    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10037    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10038    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10039    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10040    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10041    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10042    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10043    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10044
10045    /* release the tracked alloc on the exception */
10046    mov     r0, r9                      @ r0<- exception
10047    mov     r1, r10                     @ r1<- self
10048    bl      dvmReleaseTrackedAlloc      @ release the exception
10049
10050    /* restore the exception if the handler wants it */
10051    FETCH_INST()                        @ load rINST from rPC
10052    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10053    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10054    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10055    GOTO_OPCODE(ip)                     @ jump to next instruction
10056
10057.LnotCaughtLocally: @ r9=exception, r10=self
10058    /* fix stack overflow if necessary */
10059    ldrb    r1, [r10, #offThread_stackOverflowed]
10060    cmp     r1, #0                      @ did we overflow earlier?
10061    movne   r0, r10                     @ if yes: r0<- self
10062    movne   r1, r9                      @ if yes: r1<- exception
10063    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10064
10065    @ may want to show "not caught locally" debug messages here
10066#if DVM_SHOW_EXCEPTION >= 2
10067    /* call __android_log_print(prio, tag, format, ...) */
10068    /* "Exception %s from %s:%d not caught locally" */
10069    @ dvmLineNumFromPC(method, pc - method->insns)
10070    ldr     r0, [rGLUE, #offGlue_method]
10071    ldr     r1, [r0, #offMethod_insns]
10072    sub     r1, rPC, r1
10073    asr     r1, r1, #1
10074    bl      dvmLineNumFromPC
10075    str     r0, [sp, #-4]!
10076    @ dvmGetMethodSourceFile(method)
10077    ldr     r0, [rGLUE, #offGlue_method]
10078    bl      dvmGetMethodSourceFile
10079    str     r0, [sp, #-4]!
10080    @ exception->clazz->descriptor
10081    ldr     r3, [r9, #offObject_clazz]
10082    ldr     r3, [r3, #offClassObject_descriptor]
10083    @
10084    ldr     r2, strExceptionNotCaughtLocally
10085    ldr     r1, strLogTag
10086    mov     r0, #3                      @ LOG_DEBUG
10087    bl      __android_log_print
10088#endif
10089    str     r9, [r10, #offThread_exception] @ restore exception
10090    mov     r0, r9                      @ r0<- exception
10091    mov     r1, r10                     @ r1<- self
10092    bl      dvmReleaseTrackedAlloc      @ release the exception
10093    mov     r1, #0                      @ "want switch" = false
10094    b       common_gotoBail             @ bail out
10095
10096
10097    /*
10098     * Exception handling, calls through "glue code".
10099     */
10100    .if     0
10101.LexceptionOld:
10102    SAVE_PC_FP_TO_GLUE()                @ export state
10103    mov     r0, rGLUE                   @ arg to function
10104    bl      dvmMterp_exceptionThrown
10105    b       common_resumeAfterGlueCall
10106    .endif
10107
10108
10109/*
10110 * After returning from a "glued" function, pull out the updated
10111 * values and start executing at the next instruction.
10112 */
10113common_resumeAfterGlueCall:
10114    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10115    FETCH_INST()                        @ load rINST from rPC
10116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10117    GOTO_OPCODE(ip)                     @ jump to next instruction
10118
10119/*
10120 * Invalid array index.
10121 */
10122common_errArrayIndex:
10123    EXPORT_PC()
10124    ldr     r0, strArrayIndexException
10125    mov     r1, #0
10126    bl      dvmThrowException
10127    b       common_exceptionThrown
10128
10129/*
10130 * Invalid array value.
10131 */
10132common_errArrayStore:
10133    EXPORT_PC()
10134    ldr     r0, strArrayStoreException
10135    mov     r1, #0
10136    bl      dvmThrowException
10137    b       common_exceptionThrown
10138
10139/*
10140 * Integer divide or mod by zero.
10141 */
10142common_errDivideByZero:
10143    EXPORT_PC()
10144    ldr     r0, strArithmeticException
10145    ldr     r1, strDivideByZero
10146    bl      dvmThrowException
10147    b       common_exceptionThrown
10148
10149/*
10150 * Attempt to allocate an array with a negative size.
10151 */
10152common_errNegativeArraySize:
10153    EXPORT_PC()
10154    ldr     r0, strNegativeArraySizeException
10155    mov     r1, #0
10156    bl      dvmThrowException
10157    b       common_exceptionThrown
10158
10159/*
10160 * Invocation of a non-existent method.
10161 */
10162common_errNoSuchMethod:
10163    EXPORT_PC()
10164    ldr     r0, strNoSuchMethodError
10165    mov     r1, #0
10166    bl      dvmThrowException
10167    b       common_exceptionThrown
10168
10169/*
10170 * We encountered a null object when we weren't expecting one.  We
10171 * export the PC, throw a NullPointerException, and goto the exception
10172 * processing code.
10173 */
10174common_errNullObject:
10175    EXPORT_PC()
10176    ldr     r0, strNullPointerException
10177    mov     r1, #0
10178    bl      dvmThrowException
10179    b       common_exceptionThrown
10180
10181/*
10182 * For debugging, cause an immediate fault.  The source address will
10183 * be in lr (use a bl instruction to jump here).
10184 */
10185common_abort:
10186    ldr     pc, .LdeadFood
10187.LdeadFood:
10188    .word   0xdeadf00d
10189
10190/*
10191 * Spit out a "we were here", preserving all registers.  (The attempt
10192 * to save ip won't work, but we need to save an even number of
10193 * registers for EABI 64-bit stack alignment.)
10194 */
10195    .macro  SQUEAK num
10196common_squeak\num:
10197    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10198    ldr     r0, strSqueak
10199    mov     r1, #\num
10200    bl      printf
10201    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10202    bx      lr
10203    .endm
10204
10205    SQUEAK  0
10206    SQUEAK  1
10207    SQUEAK  2
10208    SQUEAK  3
10209    SQUEAK  4
10210    SQUEAK  5
10211
10212/*
10213 * Spit out the number in r0, preserving registers.
10214 */
10215common_printNum:
10216    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10217    mov     r1, r0
10218    ldr     r0, strSqueak
10219    bl      printf
10220    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10221    bx      lr
10222
10223/*
10224 * Print a newline, preserving registers.
10225 */
10226common_printNewline:
10227    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10228    ldr     r0, strNewline
10229    bl      printf
10230    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10231    bx      lr
10232
10233    /*
10234     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10235     */
10236common_printHex:
10237    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10238    mov     r1, r0
10239    ldr     r0, strPrintHex
10240    bl      printf
10241    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10242    bx      lr
10243
10244/*
10245 * Print the 64-bit quantity in r0-r1, preserving registers.
10246 */
10247common_printLong:
10248    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10249    mov     r3, r1
10250    mov     r2, r0
10251    ldr     r0, strPrintLong
10252    bl      printf
10253    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10254    bx      lr
10255
10256/*
10257 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10258 */
10259common_printMethod:
10260    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10261    bl      dvmMterpPrintMethod
10262    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10263    bx      lr
10264
10265/*
10266 * Call a C helper function that dumps regs and possibly some
10267 * additional info.  Requires the C function to be compiled in.
10268 */
10269    .if     0
10270common_dumpRegs:
10271    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10272    bl      dvmMterpDumpArmRegs
10273    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10274    bx      lr
10275    .endif
10276
10277#if 0
10278/*
10279 * Experiment on VFP mode.
10280 *
10281 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10282 *
10283 * Updates the bits specified by "mask", setting them to the values in "val".
10284 */
10285setFPSCR:
10286    and     r0, r0, r1                  @ make sure no stray bits are set
10287    fmrx    r2, fpscr                   @ get VFP reg
10288    mvn     r1, r1                      @ bit-invert mask
10289    and     r2, r2, r1                  @ clear masked bits
10290    orr     r2, r2, r0                  @ set specified bits
10291    fmxr    fpscr, r2                   @ set VFP reg
10292    mov     r0, r2                      @ return new value
10293    bx      lr
10294
10295    .align  2
10296    .global dvmConfigureFP
10297    .type   dvmConfigureFP, %function
10298dvmConfigureFP:
10299    stmfd   sp!, {ip, lr}
10300    /* 0x03000000 sets DN/FZ */
10301    /* 0x00009f00 clears the six exception enable flags */
10302    bl      common_squeak0
10303    mov     r0, #0x03000000             @ r0<- 0x03000000
10304    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10305    bl      setFPSCR
10306    ldmfd   sp!, {ip, pc}
10307#endif
10308
10309
10310/*
10311 * String references, must be close to the code that uses them.
10312 */
10313    .align  2
10314strArithmeticException:
10315    .word   .LstrArithmeticException
10316strArrayIndexException:
10317    .word   .LstrArrayIndexException
10318strArrayStoreException:
10319    .word   .LstrArrayStoreException
10320strDivideByZero:
10321    .word   .LstrDivideByZero
10322strNegativeArraySizeException:
10323    .word   .LstrNegativeArraySizeException
10324strNoSuchMethodError:
10325    .word   .LstrNoSuchMethodError
10326strNullPointerException:
10327    .word   .LstrNullPointerException
10328
10329strLogTag:
10330    .word   .LstrLogTag
10331strExceptionNotCaughtLocally:
10332    .word   .LstrExceptionNotCaughtLocally
10333
10334strNewline:
10335    .word   .LstrNewline
10336strSqueak:
10337    .word   .LstrSqueak
10338strPrintHex:
10339    .word   .LstrPrintHex
10340strPrintLong:
10341    .word   .LstrPrintLong
10342
10343/*
10344 * Zero-terminated ASCII string data.
10345 *
10346 * On ARM we have two choices: do like gcc does, and LDR from a .word
10347 * with the address, or use an ADR pseudo-op to get the address
10348 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10349 * PC-relative addressing mode and hence has a limited range, which
10350 * makes it not work well with mergeable string sections.
10351 */
10352    .section .rodata.str1.4,"aMS",%progbits,1
10353
10354.LstrBadEntryPoint:
10355    .asciz  "Bad entry point %d\n"
10356.LstrArithmeticException:
10357    .asciz  "Ljava/lang/ArithmeticException;"
10358.LstrArrayIndexException:
10359    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10360.LstrArrayStoreException:
10361    .asciz  "Ljava/lang/ArrayStoreException;"
10362.LstrClassCastException:
10363    .asciz  "Ljava/lang/ClassCastException;"
10364.LstrDivideByZero:
10365    .asciz  "divide by zero"
10366.LstrFilledNewArrayNotImpl:
10367    .asciz  "filled-new-array only implemented for objects and 'int'"
10368.LstrInternalError:
10369    .asciz  "Ljava/lang/InternalError;"
10370.LstrInstantiationError:
10371    .asciz  "Ljava/lang/InstantiationError;"
10372.LstrNegativeArraySizeException:
10373    .asciz  "Ljava/lang/NegativeArraySizeException;"
10374.LstrNoSuchMethodError:
10375    .asciz  "Ljava/lang/NoSuchMethodError;"
10376.LstrNullPointerException:
10377    .asciz  "Ljava/lang/NullPointerException;"
10378
10379.LstrLogTag:
10380    .asciz  "mterp"
10381.LstrExceptionNotCaughtLocally:
10382    .asciz  "Exception %s from %s:%d not caught locally\n"
10383
10384.LstrNewline:
10385    .asciz  "\n"
10386.LstrSqueak:
10387    .asciz  "<%d>"
10388.LstrPrintHex:
10389    .asciz  "<0x%x>"
10390.LstrPrintLong:
10391    .asciz  "<%lld>"
10392
10393
10394