InterpAsm-armv5te-vfp.S revision de75089fb7216d19e9c22cce4dc62a49513477d3
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * 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: armv5te/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    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
432    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
433    GET_VREG(r2, r1)                    @ r2<- fp[B]
434    and     r0, r0, #15
435    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
436    SET_VREG(r2, r0)                    @ fp[A]<- r2
437    GOTO_OPCODE(ip)                     @ execute next instruction
438
439
440/* ------------------------------ */
441    .balign 64
442.L_OP_MOVE_FROM16: /* 0x02 */
443/* File: armv5te/OP_MOVE_FROM16.S */
444    /* for: move/from16, move-object/from16 */
445    /* op vAA, vBBBB */
446    FETCH(r1, 1)                        @ r1<- BBBB
447    mov     r0, rINST, lsr #8           @ r0<- AA
448    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
449    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
450    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
451    SET_VREG(r2, r0)                    @ fp[AA]<- r2
452    GOTO_OPCODE(ip)                     @ jump to next instruction
453
454
455/* ------------------------------ */
456    .balign 64
457.L_OP_MOVE_16: /* 0x03 */
458/* File: armv5te/OP_MOVE_16.S */
459    /* for: move/16, move-object/16 */
460    /* op vAAAA, vBBBB */
461    FETCH(r1, 2)                        @ r1<- BBBB
462    FETCH(r0, 1)                        @ r0<- AAAA
463    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
464    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
465    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
466    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
467    GOTO_OPCODE(ip)                     @ jump to next instruction
468
469
470/* ------------------------------ */
471    .balign 64
472.L_OP_MOVE_WIDE: /* 0x04 */
473/* File: armv5te/OP_MOVE_WIDE.S */
474    /* move-wide vA, vB */
475    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
476    mov     r2, rINST, lsr #8           @ r2<- A(+)
477    mov     r3, rINST, lsr #12          @ r3<- B
478    and     r2, r2, #15
479    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
480    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
481    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
482    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
483    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
484    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
485    GOTO_OPCODE(ip)                     @ jump to next instruction
486
487
488/* ------------------------------ */
489    .balign 64
490.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
491/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
492    /* move-wide/from16 vAA, vBBBB */
493    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
494    FETCH(r3, 1)                        @ r3<- BBBB
495    mov     r2, rINST, lsr #8           @ r2<- AA
496    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
497    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
498    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
499    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
500    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
501    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
502    GOTO_OPCODE(ip)                     @ jump to next instruction
503
504
505/* ------------------------------ */
506    .balign 64
507.L_OP_MOVE_WIDE_16: /* 0x06 */
508/* File: armv5te/OP_MOVE_WIDE_16.S */
509    /* move-wide/16 vAAAA, vBBBB */
510    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
511    FETCH(r3, 2)                        @ r3<- BBBB
512    FETCH(r2, 1)                        @ r2<- AAAA
513    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
514    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
515    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
516    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
517    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
518    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
519    GOTO_OPCODE(ip)                     @ jump to next instruction
520
521
522/* ------------------------------ */
523    .balign 64
524.L_OP_MOVE_OBJECT: /* 0x07 */
525/* File: armv5te/OP_MOVE_OBJECT.S */
526/* File: armv5te/OP_MOVE.S */
527    /* for move, move-object, long-to-int */
528    /* op vA, vB */
529    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
530    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
531    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
532    GET_VREG(r2, r1)                    @ r2<- fp[B]
533    and     r0, r0, #15
534    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
535    SET_VREG(r2, r0)                    @ fp[A]<- r2
536    GOTO_OPCODE(ip)                     @ execute next instruction
537
538
539
540/* ------------------------------ */
541    .balign 64
542.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
543/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
544/* File: armv5te/OP_MOVE_FROM16.S */
545    /* for: move/from16, move-object/from16 */
546    /* op vAA, vBBBB */
547    FETCH(r1, 1)                        @ r1<- BBBB
548    mov     r0, rINST, lsr #8           @ r0<- AA
549    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
550    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
551    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
552    SET_VREG(r2, r0)                    @ fp[AA]<- r2
553    GOTO_OPCODE(ip)                     @ jump to next instruction
554
555
556
557/* ------------------------------ */
558    .balign 64
559.L_OP_MOVE_OBJECT_16: /* 0x09 */
560/* File: armv5te/OP_MOVE_OBJECT_16.S */
561/* File: armv5te/OP_MOVE_16.S */
562    /* for: move/16, move-object/16 */
563    /* op vAAAA, vBBBB */
564    FETCH(r1, 2)                        @ r1<- BBBB
565    FETCH(r0, 1)                        @ r0<- AAAA
566    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
567    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
568    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
569    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
570    GOTO_OPCODE(ip)                     @ jump to next instruction
571
572
573
574/* ------------------------------ */
575    .balign 64
576.L_OP_MOVE_RESULT: /* 0x0a */
577/* File: armv5te/OP_MOVE_RESULT.S */
578    /* for: move-result, move-result-object */
579    /* op vAA */
580    mov     r2, rINST, lsr #8           @ r2<- AA
581    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
582    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
584    SET_VREG(r0, r2)                    @ fp[AA]<- r0
585    GOTO_OPCODE(ip)                     @ jump to next instruction
586
587
588/* ------------------------------ */
589    .balign 64
590.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
591/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
592    /* move-result-wide vAA */
593    mov     r2, rINST, lsr #8           @ r2<- AA
594    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
595    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
596    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
597    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
598    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
599    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
600    GOTO_OPCODE(ip)                     @ jump to next instruction
601
602
603/* ------------------------------ */
604    .balign 64
605.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
606/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
607/* File: armv5te/OP_MOVE_RESULT.S */
608    /* for: move-result, move-result-object */
609    /* op vAA */
610    mov     r2, rINST, lsr #8           @ r2<- AA
611    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
612    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
614    SET_VREG(r0, r2)                    @ fp[AA]<- r0
615    GOTO_OPCODE(ip)                     @ jump to next instruction
616
617
618
619/* ------------------------------ */
620    .balign 64
621.L_OP_MOVE_EXCEPTION: /* 0x0d */
622/* File: armv5te/OP_MOVE_EXCEPTION.S */
623    /* move-exception vAA */
624    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
625    mov     r2, rINST, lsr #8           @ r2<- AA
626    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
627    mov     r1, #0                      @ r1<- 0
628    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
629    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
630    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
631    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
632    GOTO_OPCODE(ip)                     @ jump to next instruction
633
634
635/* ------------------------------ */
636    .balign 64
637.L_OP_RETURN_VOID: /* 0x0e */
638/* File: armv5te/OP_RETURN_VOID.S */
639    b       common_returnFromMethod
640
641
642/* ------------------------------ */
643    .balign 64
644.L_OP_RETURN: /* 0x0f */
645/* File: armv5te/OP_RETURN.S */
646    /*
647     * Return a 32-bit value.  Copies the return value into the "glue"
648     * structure, then jumps to the return handler.
649     *
650     * for: return, return-object
651     */
652    /* op vAA */
653    mov     r2, rINST, lsr #8           @ r2<- AA
654    GET_VREG(r0, r2)                    @ r0<- vAA
655    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
656    b       common_returnFromMethod
657
658
659/* ------------------------------ */
660    .balign 64
661.L_OP_RETURN_WIDE: /* 0x10 */
662/* File: armv5te/OP_RETURN_WIDE.S */
663    /*
664     * Return a 64-bit value.  Copies the return value into the "glue"
665     * structure, then jumps to the return handler.
666     */
667    /* return-wide vAA */
668    mov     r2, rINST, lsr #8           @ r2<- AA
669    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
670    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
671    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
672    stmia   r3, {r0-r1}                 @ retval<- r0/r1
673    b       common_returnFromMethod
674
675
676/* ------------------------------ */
677    .balign 64
678.L_OP_RETURN_OBJECT: /* 0x11 */
679/* File: armv5te/OP_RETURN_OBJECT.S */
680/* File: armv5te/OP_RETURN.S */
681    /*
682     * Return a 32-bit value.  Copies the return value into the "glue"
683     * structure, then jumps to the return handler.
684     *
685     * for: return, return-object
686     */
687    /* op vAA */
688    mov     r2, rINST, lsr #8           @ r2<- AA
689    GET_VREG(r0, r2)                    @ r0<- vAA
690    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
691    b       common_returnFromMethod
692
693
694
695/* ------------------------------ */
696    .balign 64
697.L_OP_CONST_4: /* 0x12 */
698/* File: armv5te/OP_CONST_4.S */
699    /* const/4 vA, #+B */
700    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
701    mov     r0, rINST, lsr #8           @ r0<- A+
702    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
703    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
704    and     r0, r0, #15
705    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
706    SET_VREG(r1, r0)                    @ fp[A]<- r1
707    GOTO_OPCODE(ip)                     @ execute next instruction
708
709
710/* ------------------------------ */
711    .balign 64
712.L_OP_CONST_16: /* 0x13 */
713/* File: armv5te/OP_CONST_16.S */
714    /* const/16 vAA, #+BBBB */
715    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
716    mov     r3, rINST, lsr #8           @ r3<- AA
717    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
718    SET_VREG(r0, r3)                    @ vAA<- r0
719    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
720    GOTO_OPCODE(ip)                     @ jump to next instruction
721
722
723/* ------------------------------ */
724    .balign 64
725.L_OP_CONST: /* 0x14 */
726/* File: armv5te/OP_CONST.S */
727    /* const vAA, #+BBBBbbbb */
728    mov     r3, rINST, lsr #8           @ r3<- AA
729    FETCH(r0, 1)                        @ r0<- bbbb (low)
730    FETCH(r1, 2)                        @ r1<- BBBB (high)
731    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
732    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
733    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
734    SET_VREG(r0, r3)                    @ vAA<- r0
735    GOTO_OPCODE(ip)                     @ jump to next instruction
736
737
738/* ------------------------------ */
739    .balign 64
740.L_OP_CONST_HIGH16: /* 0x15 */
741/* File: armv5te/OP_CONST_HIGH16.S */
742    /* const/high16 vAA, #+BBBB0000 */
743    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
744    mov     r3, rINST, lsr #8           @ r3<- AA
745    mov     r0, r0, lsl #16             @ r0<- BBBB0000
746    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
747    SET_VREG(r0, r3)                    @ vAA<- r0
748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
749    GOTO_OPCODE(ip)                     @ jump to next instruction
750
751
752/* ------------------------------ */
753    .balign 64
754.L_OP_CONST_WIDE_16: /* 0x16 */
755/* File: armv5te/OP_CONST_WIDE_16.S */
756    /* const-wide/16 vAA, #+BBBB */
757    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
758    mov     r3, rINST, lsr #8           @ r3<- AA
759    mov     r1, r0, asr #31             @ r1<- ssssssss
760    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
761    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
763    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
764    GOTO_OPCODE(ip)                     @ jump to next instruction
765
766
767/* ------------------------------ */
768    .balign 64
769.L_OP_CONST_WIDE_32: /* 0x17 */
770/* File: armv5te/OP_CONST_WIDE_32.S */
771    /* const-wide/32 vAA, #+BBBBbbbb */
772    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
773    mov     r3, rINST, lsr #8           @ r3<- AA
774    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
775    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
776    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
777    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
778    mov     r1, r0, asr #31             @ r1<- ssssssss
779    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
780    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
781    GOTO_OPCODE(ip)                     @ jump to next instruction
782
783
784/* ------------------------------ */
785    .balign 64
786.L_OP_CONST_WIDE: /* 0x18 */
787/* File: armv5te/OP_CONST_WIDE.S */
788    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
789    FETCH(r0, 1)                        @ r0<- bbbb (low)
790    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
791    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
792    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
793    FETCH(r3, 4)                        @ r3<- HHHH (high)
794    mov     r9, rINST, lsr #8           @ r9<- AA
795    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
796    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
797    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
799    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
800    GOTO_OPCODE(ip)                     @ jump to next instruction
801
802
803/* ------------------------------ */
804    .balign 64
805.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
806/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
807    /* const-wide/high16 vAA, #+BBBB000000000000 */
808    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
809    mov     r3, rINST, lsr #8           @ r3<- AA
810    mov     r0, #0                      @ r0<- 00000000
811    mov     r1, r1, lsl #16             @ r1<- BBBB0000
812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
813    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
814    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
815    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
816    GOTO_OPCODE(ip)                     @ jump to next instruction
817
818
819/* ------------------------------ */
820    .balign 64
821.L_OP_CONST_STRING: /* 0x1a */
822/* File: armv5te/OP_CONST_STRING.S */
823    /* const/string vAA, String@BBBB */
824    FETCH(r1, 1)                        @ r1<- BBBB
825    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
826    mov     r9, rINST, lsr #8           @ r9<- AA
827    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
828    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
829    cmp     r0, #0                      @ not yet resolved?
830    beq     .LOP_CONST_STRING_resolve
831    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
833    SET_VREG(r0, r9)                    @ vAA<- r0
834    GOTO_OPCODE(ip)                     @ jump to next instruction
835
836/* ------------------------------ */
837    .balign 64
838.L_OP_CONST_STRING_JUMBO: /* 0x1b */
839/* File: armv5te/OP_CONST_STRING_JUMBO.S */
840    /* const/string vAA, String@BBBBBBBB */
841    FETCH(r0, 1)                        @ r0<- bbbb (low)
842    FETCH(r1, 2)                        @ r1<- BBBB (high)
843    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
844    mov     r9, rINST, lsr #8           @ r9<- AA
845    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
846    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
847    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
848    cmp     r0, #0
849    beq     .LOP_CONST_STRING_JUMBO_resolve
850    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
851    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
852    SET_VREG(r0, r9)                    @ vAA<- r0
853    GOTO_OPCODE(ip)                     @ jump to next instruction
854
855/* ------------------------------ */
856    .balign 64
857.L_OP_CONST_CLASS: /* 0x1c */
858/* File: armv5te/OP_CONST_CLASS.S */
859    /* const/class vAA, Class@BBBB */
860    FETCH(r1, 1)                        @ r1<- BBBB
861    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
862    mov     r9, rINST, lsr #8           @ r9<- AA
863    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
864    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
865    cmp     r0, #0                      @ not yet resolved?
866    beq     .LOP_CONST_CLASS_resolve
867    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
869    SET_VREG(r0, r9)                    @ vAA<- r0
870    GOTO_OPCODE(ip)                     @ jump to next instruction
871
872/* ------------------------------ */
873    .balign 64
874.L_OP_MONITOR_ENTER: /* 0x1d */
875/* File: armv5te/OP_MONITOR_ENTER.S */
876    /*
877     * Synchronize on an object.
878     */
879    /* monitor-enter vAA */
880    mov     r2, rINST, lsr #8           @ r2<- AA
881    GET_VREG(r1, r2)                    @ r1<- vAA (object)
882    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
883    cmp     r1, #0                      @ null object?
884    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
885    beq     common_errNullObject        @ null object, throw an exception
886    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
887    bl      dvmLockObject               @ call(self, obj)
888#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
889    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
890    ldr     r1, [r0, #offThread_exception] @ check for exception
891    cmp     r1, #0
892    bne     common_exceptionThrown      @ exception raised, bail out
893#endif
894    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
895    GOTO_OPCODE(ip)                     @ jump to next instruction
896
897
898/* ------------------------------ */
899    .balign 64
900.L_OP_MONITOR_EXIT: /* 0x1e */
901/* File: armv5te/OP_MONITOR_EXIT.S */
902    /*
903     * Unlock an object.
904     *
905     * Exceptions that occur when unlocking a monitor need to appear as
906     * if they happened at the following instruction.  See the Dalvik
907     * instruction spec.
908     */
909    /* monitor-exit vAA */
910    mov     r2, rINST, lsr #8           @ r2<- AA
911    EXPORT_PC()                         @ before fetch: export the PC
912    GET_VREG(r1, r2)                    @ r1<- vAA (object)
913    cmp     r1, #0                      @ null object?
914    beq     1f                          @ yes
915    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
916    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
917    cmp     r0, #0                      @ failed?
918    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
919    beq     common_exceptionThrown      @ yes, exception is pending
920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
921    GOTO_OPCODE(ip)                     @ jump to next instruction
9221:
923    FETCH_ADVANCE_INST(1)               @ advance before throw
924    b      common_errNullObject
925
926
927/* ------------------------------ */
928    .balign 64
929.L_OP_CHECK_CAST: /* 0x1f */
930/* File: armv5te/OP_CHECK_CAST.S */
931    /*
932     * Check to see if a cast from one class to another is allowed.
933     */
934    /* check-cast vAA, class@BBBB */
935    mov     r3, rINST, lsr #8           @ r3<- AA
936    FETCH(r2, 1)                        @ r2<- BBBB
937    GET_VREG(r9, r3)                    @ r9<- object
938    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
939    cmp     r9, #0                      @ is object null?
940    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
941    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
942    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
943    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
944    cmp     r1, #0                      @ have we resolved this before?
945    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
946.LOP_CHECK_CAST_resolved:
947    cmp     r0, r1                      @ same class (trivial success)?
948    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
949.LOP_CHECK_CAST_okay:
950    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
952    GOTO_OPCODE(ip)                     @ jump to next instruction
953
954/* ------------------------------ */
955    .balign 64
956.L_OP_INSTANCE_OF: /* 0x20 */
957/* File: armv5te/OP_INSTANCE_OF.S */
958    /*
959     * Check to see if an object reference is an instance of a class.
960     *
961     * Most common situation is a non-null object, being compared against
962     * an already-resolved class.
963     */
964    /* instance-of vA, vB, class@CCCC */
965    mov     r3, rINST, lsr #12          @ r3<- B
966    mov     r9, rINST, lsr #8           @ r9<- A+
967    GET_VREG(r0, r3)                    @ r0<- vB (object)
968    and     r9, r9, #15                 @ r9<- A
969    cmp     r0, #0                      @ is object null?
970    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
971    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
972    FETCH(r3, 1)                        @ r3<- CCCC
973    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
974    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
975    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
976    cmp     r1, #0                      @ have we resolved this before?
977    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
978.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
979    cmp     r0, r1                      @ same class (trivial success)?
980    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
981    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
982
983/* ------------------------------ */
984    .balign 64
985.L_OP_ARRAY_LENGTH: /* 0x21 */
986/* File: armv5te/OP_ARRAY_LENGTH.S */
987    /*
988     * Return the length of an array.
989     */
990    mov     r1, rINST, lsr #12          @ r1<- B
991    mov     r2, rINST, lsr #8           @ r2<- A+
992    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
993    and     r2, r2, #15                 @ r2<- A
994    cmp     r0, #0                      @ is object null?
995    beq     common_errNullObject        @ yup, fail
996    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
997    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
999    SET_VREG(r3, r2)                    @ vB<- length
1000    GOTO_OPCODE(ip)                     @ jump to next instruction
1001
1002
1003/* ------------------------------ */
1004    .balign 64
1005.L_OP_NEW_INSTANCE: /* 0x22 */
1006/* File: armv5te/OP_NEW_INSTANCE.S */
1007    /*
1008     * Create a new instance of a class.
1009     */
1010    /* new-instance vAA, class@BBBB */
1011    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1012    FETCH(r1, 1)                        @ r1<- BBBB
1013    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1014    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1015    EXPORT_PC()                         @ req'd for init, resolve, alloc
1016    cmp     r0, #0                      @ already resolved?
1017    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1018.LOP_NEW_INSTANCE_resolved:   @ r0=class
1019    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1020    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1021    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1022.LOP_NEW_INSTANCE_initialized: @ r0=class
1023    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1024    bl      dvmAllocObject              @ r0<- new object
1025    b       .LOP_NEW_INSTANCE_finish          @ continue
1026
1027/* ------------------------------ */
1028    .balign 64
1029.L_OP_NEW_ARRAY: /* 0x23 */
1030/* File: armv5te/OP_NEW_ARRAY.S */
1031    /*
1032     * Allocate an array of objects, specified with the array class
1033     * and a count.
1034     *
1035     * The verifier guarantees that this is an array class, so we don't
1036     * check for it here.
1037     */
1038    /* new-array vA, vB, class@CCCC */
1039    mov     r0, rINST, lsr #12          @ r0<- B
1040    FETCH(r2, 1)                        @ r2<- CCCC
1041    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1042    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1043    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1044    cmp     r1, #0                      @ check length
1045    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1046    bmi     common_errNegativeArraySize @ negative length, bail
1047    cmp     r0, #0                      @ already resolved?
1048    EXPORT_PC()                         @ req'd for resolve, alloc
1049    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1050    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1051
1052/* ------------------------------ */
1053    .balign 64
1054.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1055/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1056    /*
1057     * Create a new array with elements filled from registers.
1058     *
1059     * for: filled-new-array, filled-new-array/range
1060     */
1061    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1062    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1063    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1064    FETCH(r1, 1)                        @ r1<- BBBB
1065    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1066    EXPORT_PC()                         @ need for resolve and alloc
1067    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1068    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1069    cmp     r0, #0                      @ already resolved?
1070    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10718:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1072    mov     r2, #0                      @ r2<- false
1073    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1074    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1075    cmp     r0, #0                      @ got null?
1076    beq     common_exceptionThrown      @ yes, handle exception
1077    b       .LOP_FILLED_NEW_ARRAY_continue
1078
1079/* ------------------------------ */
1080    .balign 64
1081.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1082/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1083/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1084    /*
1085     * Create a new array with elements filled from registers.
1086     *
1087     * for: filled-new-array, filled-new-array/range
1088     */
1089    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1090    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1091    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1092    FETCH(r1, 1)                        @ r1<- BBBB
1093    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1094    EXPORT_PC()                         @ need for resolve and alloc
1095    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1096    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1097    cmp     r0, #0                      @ already resolved?
1098    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10998:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1100    mov     r2, #0                      @ r2<- false
1101    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1102    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1103    cmp     r0, #0                      @ got null?
1104    beq     common_exceptionThrown      @ yes, handle exception
1105    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1106
1107
1108/* ------------------------------ */
1109    .balign 64
1110.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1111/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1112    /* fill-array-data vAA, +BBBBBBBB */
1113    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1114    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1115    mov     r3, rINST, lsr #8           @ r3<- AA
1116    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1117    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1118    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1119    EXPORT_PC();
1120    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1121    cmp     r0, #0                      @ 0 means an exception is thrown
1122    beq     common_exceptionThrown      @ has exception
1123    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1124    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1125    GOTO_OPCODE(ip)                     @ jump to next instruction
1126
1127/* ------------------------------ */
1128    .balign 64
1129.L_OP_THROW: /* 0x27 */
1130/* File: armv5te/OP_THROW.S */
1131    /*
1132     * Throw an exception object in the current thread.
1133     */
1134    /* throw vAA */
1135    mov     r2, rINST, lsr #8           @ r2<- AA
1136    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1137    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1138    EXPORT_PC()                         @ exception handler can throw
1139    cmp     r1, #0                      @ null object?
1140    beq     common_errNullObject        @ yes, throw an NPE instead
1141    @ bypass dvmSetException, just store it
1142    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1143    b       common_exceptionThrown
1144
1145
1146/* ------------------------------ */
1147    .balign 64
1148.L_OP_GOTO: /* 0x28 */
1149/* File: armv5te/OP_GOTO.S */
1150    /*
1151     * Unconditional branch, 8-bit offset.
1152     *
1153     * The branch distance is a signed code-unit offset, which we need to
1154     * double to get a byte offset.
1155     */
1156    /* goto +AA */
1157    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1158    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1159    mov     r9, r9, lsl #1              @ r9<- byte offset
1160    bmi     common_backwardBranch       @ backward branch, do periodic checks
1161#if defined(WITH_JIT)
1162    GET_JIT_PROF_TABLE(r0)
1163    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1164    cmp     r0,#0
1165    bne     common_updateProfile
1166    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1167    GOTO_OPCODE(ip)                     @ jump to next instruction
1168#else
1169    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1171    GOTO_OPCODE(ip)                     @ jump to next instruction
1172#endif
1173
1174/* ------------------------------ */
1175    .balign 64
1176.L_OP_GOTO_16: /* 0x29 */
1177/* File: armv5te/OP_GOTO_16.S */
1178    /*
1179     * Unconditional branch, 16-bit offset.
1180     *
1181     * The branch distance is a signed code-unit offset, which we need to
1182     * double to get a byte offset.
1183     */
1184    /* goto/16 +AAAA */
1185    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1186    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1187    bmi     common_backwardBranch       @ backward branch, do periodic checks
1188#if defined(WITH_JIT)
1189    GET_JIT_PROF_TABLE(r0)
1190    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1191    cmp     r0,#0
1192    bne     common_updateProfile
1193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1194    GOTO_OPCODE(ip)                     @ jump to next instruction
1195#else
1196    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1198    GOTO_OPCODE(ip)                     @ jump to next instruction
1199#endif
1200
1201
1202/* ------------------------------ */
1203    .balign 64
1204.L_OP_GOTO_32: /* 0x2a */
1205/* File: armv5te/OP_GOTO_32.S */
1206    /*
1207     * Unconditional branch, 32-bit offset.
1208     *
1209     * The branch distance is a signed code-unit offset, which we need to
1210     * double to get a byte offset.
1211     *
1212     * Unlike most opcodes, this one is allowed to branch to itself, so
1213     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1214     * instruction doesn't affect the V flag, so we need to clear it
1215     * explicitly.
1216     */
1217    /* goto/32 +AAAAAAAA */
1218    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1219    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1220    cmp     ip, ip                      @ (clear V flag during stall)
1221    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1222    mov     r9, r0, asl #1              @ r9<- byte offset
1223    ble     common_backwardBranch       @ backward branch, do periodic checks
1224#if defined(WITH_JIT)
1225    GET_JIT_PROF_TABLE(r0)
1226    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1227    cmp     r0,#0
1228    bne     common_updateProfile
1229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1230    GOTO_OPCODE(ip)                     @ jump to next instruction
1231#else
1232    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1234    GOTO_OPCODE(ip)                     @ jump to next instruction
1235#endif
1236
1237/* ------------------------------ */
1238    .balign 64
1239.L_OP_PACKED_SWITCH: /* 0x2b */
1240/* File: armv5te/OP_PACKED_SWITCH.S */
1241    /*
1242     * Handle a packed-switch or sparse-switch instruction.  In both cases
1243     * we decode it and hand it off to a helper function.
1244     *
1245     * We don't really expect backward branches in a switch statement, but
1246     * they're perfectly legal, so we check for them here.
1247     *
1248     * for: packed-switch, sparse-switch
1249     */
1250    /* op vAA, +BBBB */
1251    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1252    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1253    mov     r3, rINST, lsr #8           @ r3<- AA
1254    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1255    GET_VREG(r1, r3)                    @ r1<- vAA
1256    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1257    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1258    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1259    bmi     common_backwardBranch       @ backward branch, do periodic checks
1260    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1261#if defined(WITH_JIT)
1262    GET_JIT_PROF_TABLE(r0)
1263    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1264    cmp     r0,#0
1265    bne     common_updateProfile
1266    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1267    GOTO_OPCODE(ip)                     @ jump to next instruction
1268#else
1269    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1270    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1271    GOTO_OPCODE(ip)                     @ jump to next instruction
1272#endif
1273
1274
1275/* ------------------------------ */
1276    .balign 64
1277.L_OP_SPARSE_SWITCH: /* 0x2c */
1278/* File: armv5te/OP_SPARSE_SWITCH.S */
1279/* File: armv5te/OP_PACKED_SWITCH.S */
1280    /*
1281     * Handle a packed-switch or sparse-switch instruction.  In both cases
1282     * we decode it and hand it off to a helper function.
1283     *
1284     * We don't really expect backward branches in a switch statement, but
1285     * they're perfectly legal, so we check for them here.
1286     *
1287     * for: packed-switch, sparse-switch
1288     */
1289    /* op vAA, +BBBB */
1290    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1291    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1292    mov     r3, rINST, lsr #8           @ r3<- AA
1293    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1294    GET_VREG(r1, r3)                    @ r1<- vAA
1295    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1296    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1297    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1298    bmi     common_backwardBranch       @ backward branch, do periodic checks
1299    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1300#if defined(WITH_JIT)
1301    GET_JIT_PROF_TABLE(r0)
1302    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1303    cmp     r0,#0
1304    bne     common_updateProfile
1305    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1306    GOTO_OPCODE(ip)                     @ jump to next instruction
1307#else
1308    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1309    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1310    GOTO_OPCODE(ip)                     @ jump to next instruction
1311#endif
1312
1313
1314
1315/* ------------------------------ */
1316    .balign 64
1317.L_OP_CMPL_FLOAT: /* 0x2d */
1318/* File: arm-vfp/OP_CMPL_FLOAT.S */
1319    /*
1320     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1321     * destination register based on the results of the comparison.
1322     *
1323     * int compare(x, y) {
1324     *     if (x == y) {
1325     *         return 0;
1326     *     } else if (x > y) {
1327     *         return 1;
1328     *     } else if (x < y) {
1329     *         return -1;
1330     *     } else {
1331     *         return -1;
1332     *     }
1333     * }
1334     */
1335    /* op vAA, vBB, vCC */
1336    FETCH(r0, 1)                        @ r0<- CCBB
1337    mov     r9, rINST, lsr #8           @ r9<- AA
1338    and     r2, r0, #255                @ r2<- BB
1339    mov     r3, r0, lsr #8              @ r3<- CC
1340    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1341    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1342    flds    s0, [r2]                    @ s0<- vBB
1343    flds    s1, [r3]                    @ s1<- vCC
1344    fcmpes  s0, s1                      @ compare (vBB, vCC)
1345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1346    mvn     r0, #0                      @ r0<- -1 (default)
1347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1348    fmstat                              @ export status flags
1349    movgt   r0, #1                      @ (greater than) r1<- 1
1350    moveq   r0, #0                      @ (equal) r1<- 0
1351    b       .LOP_CMPL_FLOAT_finish          @ argh
1352
1353
1354/* ------------------------------ */
1355    .balign 64
1356.L_OP_CMPG_FLOAT: /* 0x2e */
1357/* File: arm-vfp/OP_CMPG_FLOAT.S */
1358    /*
1359     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1360     * destination register based on the results of the comparison.
1361     *
1362     * int compare(x, y) {
1363     *     if (x == y) {
1364     *         return 0;
1365     *     } else if (x < y) {
1366     *         return -1;
1367     *     } else if (x > y) {
1368     *         return 1;
1369     *     } else {
1370     *         return 1;
1371     *     }
1372     * }
1373     */
1374    /* op vAA, vBB, vCC */
1375    FETCH(r0, 1)                        @ r0<- CCBB
1376    mov     r9, rINST, lsr #8           @ r9<- AA
1377    and     r2, r0, #255                @ r2<- BB
1378    mov     r3, r0, lsr #8              @ r3<- CC
1379    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1380    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1381    flds    s0, [r2]                    @ s0<- vBB
1382    flds    s1, [r3]                    @ s1<- vCC
1383    fcmpes  s0, s1                      @ compare (vBB, vCC)
1384    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1385    mov     r0, #1                      @ r0<- 1 (default)
1386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1387    fmstat                              @ export status flags
1388    mvnmi   r0, #0                      @ (less than) r1<- -1
1389    moveq   r0, #0                      @ (equal) r1<- 0
1390    b       .LOP_CMPG_FLOAT_finish          @ argh
1391
1392
1393/* ------------------------------ */
1394    .balign 64
1395.L_OP_CMPL_DOUBLE: /* 0x2f */
1396/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1397    /*
1398     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1399     * destination register based on the results of the comparison.
1400     *
1401     * int compare(x, y) {
1402     *     if (x == y) {
1403     *         return 0;
1404     *     } else if (x > y) {
1405     *         return 1;
1406     *     } else if (x < y) {
1407     *         return -1;
1408     *     } else {
1409     *         return -1;
1410     *     }
1411     * }
1412     */
1413    /* op vAA, vBB, vCC */
1414    FETCH(r0, 1)                        @ r0<- CCBB
1415    mov     r9, rINST, lsr #8           @ r9<- AA
1416    and     r2, r0, #255                @ r2<- BB
1417    mov     r3, r0, lsr #8              @ r3<- CC
1418    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1419    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1420    fldd    d0, [r2]                    @ d0<- vBB
1421    fldd    d1, [r3]                    @ d1<- vCC
1422    fcmped  d0, d1                      @ compare (vBB, vCC)
1423    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1424    mvn     r0, #0                      @ r0<- -1 (default)
1425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1426    fmstat                              @ export status flags
1427    movgt   r0, #1                      @ (greater than) r1<- 1
1428    moveq   r0, #0                      @ (equal) r1<- 0
1429    b       .LOP_CMPL_DOUBLE_finish          @ argh
1430
1431
1432/* ------------------------------ */
1433    .balign 64
1434.L_OP_CMPG_DOUBLE: /* 0x30 */
1435/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1436    /*
1437     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1438     * destination register based on the results of the comparison.
1439     *
1440     * int compare(x, y) {
1441     *     if (x == y) {
1442     *         return 0;
1443     *     } else if (x < y) {
1444     *         return -1;
1445     *     } else if (x > y) {
1446     *         return 1;
1447     *     } else {
1448     *         return 1;
1449     *     }
1450     * }
1451     */
1452    /* op vAA, vBB, vCC */
1453    FETCH(r0, 1)                        @ r0<- CCBB
1454    mov     r9, rINST, lsr #8           @ r9<- AA
1455    and     r2, r0, #255                @ r2<- BB
1456    mov     r3, r0, lsr #8              @ r3<- CC
1457    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1458    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1459    fldd    d0, [r2]                    @ d0<- vBB
1460    fldd    d1, [r3]                    @ d1<- vCC
1461    fcmped  d0, d1                      @ compare (vBB, vCC)
1462    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1463    mov     r0, #1                      @ r0<- 1 (default)
1464    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1465    fmstat                              @ export status flags
1466    mvnmi   r0, #0                      @ (less than) r1<- -1
1467    moveq   r0, #0                      @ (equal) r1<- 0
1468    b       .LOP_CMPG_DOUBLE_finish          @ argh
1469
1470
1471/* ------------------------------ */
1472    .balign 64
1473.L_OP_CMP_LONG: /* 0x31 */
1474/* File: armv5te/OP_CMP_LONG.S */
1475    /*
1476     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1477     * register based on the results of the comparison.
1478     *
1479     * We load the full values with LDM, but in practice many values could
1480     * be resolved by only looking at the high word.  This could be made
1481     * faster or slower by splitting the LDM into a pair of LDRs.
1482     *
1483     * If we just wanted to set condition flags, we could do this:
1484     *  subs    ip, r0, r2
1485     *  sbcs    ip, r1, r3
1486     *  subeqs  ip, r0, r2
1487     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1488     * integer value, which we can do with 2 conditional mov/mvn instructions
1489     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1490     * us a constant 5-cycle path plus a branch at the end to the
1491     * instruction epilogue code.  The multi-compare approach below needs
1492     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1493     * in the worst case (the 64-bit values are equal).
1494     */
1495    /* cmp-long vAA, vBB, vCC */
1496    FETCH(r0, 1)                        @ r0<- CCBB
1497    mov     r9, rINST, lsr #8           @ r9<- AA
1498    and     r2, r0, #255                @ r2<- BB
1499    mov     r3, r0, lsr #8              @ r3<- CC
1500    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1501    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1502    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1503    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1504    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1505    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1506    bgt     .LOP_CMP_LONG_greater
1507    subs    r1, r0, r2                  @ r1<- r0 - r2
1508    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1509    bne     .LOP_CMP_LONG_less
1510    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1511
1512/* ------------------------------ */
1513    .balign 64
1514.L_OP_IF_EQ: /* 0x32 */
1515/* File: armv5te/OP_IF_EQ.S */
1516/* File: armv5te/bincmp.S */
1517    /*
1518     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1519     * fragment that specifies the *reverse* comparison to perform, e.g.
1520     * for "if-le" you would use "gt".
1521     *
1522     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1523     */
1524    /* if-cmp vA, vB, +CCCC */
1525    mov     r0, rINST, lsr #8           @ r0<- A+
1526    mov     r1, rINST, lsr #12          @ r1<- B
1527    and     r0, r0, #15
1528    GET_VREG(r3, r1)                    @ r3<- vB
1529    GET_VREG(r2, r0)                    @ r2<- vA
1530    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1531    cmp     r2, r3                      @ compare (vA, vB)
1532    bne  1f                      @ branch to 1 if comparison failed
1533    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1534    movs    r9, r9, asl #1              @ convert to bytes, check sign
1535    bmi     common_backwardBranch       @ yes, do periodic checks
15361:
1537#if defined(WITH_JIT)
1538    GET_JIT_PROF_TABLE(r0)
1539    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1540    b        common_testUpdateProfile
1541#else
1542    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1543    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1544    GOTO_OPCODE(ip)                     @ jump to next instruction
1545#endif
1546
1547
1548
1549/* ------------------------------ */
1550    .balign 64
1551.L_OP_IF_NE: /* 0x33 */
1552/* File: armv5te/OP_IF_NE.S */
1553/* File: armv5te/bincmp.S */
1554    /*
1555     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1556     * fragment that specifies the *reverse* comparison to perform, e.g.
1557     * for "if-le" you would use "gt".
1558     *
1559     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1560     */
1561    /* if-cmp vA, vB, +CCCC */
1562    mov     r0, rINST, lsr #8           @ r0<- A+
1563    mov     r1, rINST, lsr #12          @ r1<- B
1564    and     r0, r0, #15
1565    GET_VREG(r3, r1)                    @ r3<- vB
1566    GET_VREG(r2, r0)                    @ r2<- vA
1567    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1568    cmp     r2, r3                      @ compare (vA, vB)
1569    beq  1f                      @ branch to 1 if comparison failed
1570    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1571    movs    r9, r9, asl #1              @ convert to bytes, check sign
1572    bmi     common_backwardBranch       @ yes, do periodic checks
15731:
1574#if defined(WITH_JIT)
1575    GET_JIT_PROF_TABLE(r0)
1576    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1577    b        common_testUpdateProfile
1578#else
1579    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1581    GOTO_OPCODE(ip)                     @ jump to next instruction
1582#endif
1583
1584
1585
1586/* ------------------------------ */
1587    .balign 64
1588.L_OP_IF_LT: /* 0x34 */
1589/* File: armv5te/OP_IF_LT.S */
1590/* File: armv5te/bincmp.S */
1591    /*
1592     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1593     * fragment that specifies the *reverse* comparison to perform, e.g.
1594     * for "if-le" you would use "gt".
1595     *
1596     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1597     */
1598    /* if-cmp vA, vB, +CCCC */
1599    mov     r0, rINST, lsr #8           @ r0<- A+
1600    mov     r1, rINST, lsr #12          @ r1<- B
1601    and     r0, r0, #15
1602    GET_VREG(r3, r1)                    @ r3<- vB
1603    GET_VREG(r2, r0)                    @ r2<- vA
1604    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1605    cmp     r2, r3                      @ compare (vA, vB)
1606    bge  1f                      @ branch to 1 if comparison failed
1607    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1608    movs    r9, r9, asl #1              @ convert to bytes, check sign
1609    bmi     common_backwardBranch       @ yes, do periodic checks
16101:
1611#if defined(WITH_JIT)
1612    GET_JIT_PROF_TABLE(r0)
1613    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1614    b        common_testUpdateProfile
1615#else
1616    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1617    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1618    GOTO_OPCODE(ip)                     @ jump to next instruction
1619#endif
1620
1621
1622
1623/* ------------------------------ */
1624    .balign 64
1625.L_OP_IF_GE: /* 0x35 */
1626/* File: armv5te/OP_IF_GE.S */
1627/* File: armv5te/bincmp.S */
1628    /*
1629     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1630     * fragment that specifies the *reverse* comparison to perform, e.g.
1631     * for "if-le" you would use "gt".
1632     *
1633     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1634     */
1635    /* if-cmp vA, vB, +CCCC */
1636    mov     r0, rINST, lsr #8           @ r0<- A+
1637    mov     r1, rINST, lsr #12          @ r1<- B
1638    and     r0, r0, #15
1639    GET_VREG(r3, r1)                    @ r3<- vB
1640    GET_VREG(r2, r0)                    @ r2<- vA
1641    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1642    cmp     r2, r3                      @ compare (vA, vB)
1643    blt  1f                      @ branch to 1 if comparison failed
1644    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1645    movs    r9, r9, asl #1              @ convert to bytes, check sign
1646    bmi     common_backwardBranch       @ yes, do periodic checks
16471:
1648#if defined(WITH_JIT)
1649    GET_JIT_PROF_TABLE(r0)
1650    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1651    b        common_testUpdateProfile
1652#else
1653    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1655    GOTO_OPCODE(ip)                     @ jump to next instruction
1656#endif
1657
1658
1659
1660/* ------------------------------ */
1661    .balign 64
1662.L_OP_IF_GT: /* 0x36 */
1663/* File: armv5te/OP_IF_GT.S */
1664/* File: armv5te/bincmp.S */
1665    /*
1666     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1667     * fragment that specifies the *reverse* comparison to perform, e.g.
1668     * for "if-le" you would use "gt".
1669     *
1670     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1671     */
1672    /* if-cmp vA, vB, +CCCC */
1673    mov     r0, rINST, lsr #8           @ r0<- A+
1674    mov     r1, rINST, lsr #12          @ r1<- B
1675    and     r0, r0, #15
1676    GET_VREG(r3, r1)                    @ r3<- vB
1677    GET_VREG(r2, r0)                    @ r2<- vA
1678    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1679    cmp     r2, r3                      @ compare (vA, vB)
1680    ble  1f                      @ branch to 1 if comparison failed
1681    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1682    movs    r9, r9, asl #1              @ convert to bytes, check sign
1683    bmi     common_backwardBranch       @ yes, do periodic checks
16841:
1685#if defined(WITH_JIT)
1686    GET_JIT_PROF_TABLE(r0)
1687    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1688    b        common_testUpdateProfile
1689#else
1690    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1691    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1692    GOTO_OPCODE(ip)                     @ jump to next instruction
1693#endif
1694
1695
1696
1697/* ------------------------------ */
1698    .balign 64
1699.L_OP_IF_LE: /* 0x37 */
1700/* File: armv5te/OP_IF_LE.S */
1701/* File: armv5te/bincmp.S */
1702    /*
1703     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1704     * fragment that specifies the *reverse* comparison to perform, e.g.
1705     * for "if-le" you would use "gt".
1706     *
1707     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1708     */
1709    /* if-cmp vA, vB, +CCCC */
1710    mov     r0, rINST, lsr #8           @ r0<- A+
1711    mov     r1, rINST, lsr #12          @ r1<- B
1712    and     r0, r0, #15
1713    GET_VREG(r3, r1)                    @ r3<- vB
1714    GET_VREG(r2, r0)                    @ r2<- vA
1715    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1716    cmp     r2, r3                      @ compare (vA, vB)
1717    bgt  1f                      @ branch to 1 if comparison failed
1718    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1719    movs    r9, r9, asl #1              @ convert to bytes, check sign
1720    bmi     common_backwardBranch       @ yes, do periodic checks
17211:
1722#if defined(WITH_JIT)
1723    GET_JIT_PROF_TABLE(r0)
1724    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1725    b        common_testUpdateProfile
1726#else
1727    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1729    GOTO_OPCODE(ip)                     @ jump to next instruction
1730#endif
1731
1732
1733
1734/* ------------------------------ */
1735    .balign 64
1736.L_OP_IF_EQZ: /* 0x38 */
1737/* File: armv5te/OP_IF_EQZ.S */
1738/* File: armv5te/zcmp.S */
1739    /*
1740     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1741     * fragment that specifies the *reverse* comparison to perform, e.g.
1742     * for "if-le" you would use "gt".
1743     *
1744     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1745     */
1746    /* if-cmp vAA, +BBBB */
1747    mov     r0, rINST, lsr #8           @ r0<- AA
1748    GET_VREG(r2, r0)                    @ r2<- vAA
1749    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1750    cmp     r2, #0                      @ compare (vA, 0)
1751    bne  1f                      @ branch to 1 if comparison failed
1752    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1753    movs    r9, r9, asl #1              @ convert to bytes, check sign
1754    bmi     common_backwardBranch       @ backward branch, do periodic checks
17551:
1756#if defined(WITH_JIT)
1757    GET_JIT_PROF_TABLE(r0)
1758    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1759    cmp     r0,#0
1760    bne     common_updateProfile
1761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1762    GOTO_OPCODE(ip)                     @ jump to next instruction
1763#else
1764    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1765    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1766    GOTO_OPCODE(ip)                     @ jump to next instruction
1767#endif
1768
1769
1770
1771/* ------------------------------ */
1772    .balign 64
1773.L_OP_IF_NEZ: /* 0x39 */
1774/* File: armv5te/OP_IF_NEZ.S */
1775/* File: armv5te/zcmp.S */
1776    /*
1777     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1778     * fragment that specifies the *reverse* comparison to perform, e.g.
1779     * for "if-le" you would use "gt".
1780     *
1781     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1782     */
1783    /* if-cmp vAA, +BBBB */
1784    mov     r0, rINST, lsr #8           @ r0<- AA
1785    GET_VREG(r2, r0)                    @ r2<- vAA
1786    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1787    cmp     r2, #0                      @ compare (vA, 0)
1788    beq  1f                      @ branch to 1 if comparison failed
1789    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1790    movs    r9, r9, asl #1              @ convert to bytes, check sign
1791    bmi     common_backwardBranch       @ backward branch, do periodic checks
17921:
1793#if defined(WITH_JIT)
1794    GET_JIT_PROF_TABLE(r0)
1795    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1796    cmp     r0,#0
1797    bne     common_updateProfile
1798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1799    GOTO_OPCODE(ip)                     @ jump to next instruction
1800#else
1801    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1803    GOTO_OPCODE(ip)                     @ jump to next instruction
1804#endif
1805
1806
1807
1808/* ------------------------------ */
1809    .balign 64
1810.L_OP_IF_LTZ: /* 0x3a */
1811/* File: armv5te/OP_IF_LTZ.S */
1812/* File: armv5te/zcmp.S */
1813    /*
1814     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1815     * fragment that specifies the *reverse* comparison to perform, e.g.
1816     * for "if-le" you would use "gt".
1817     *
1818     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1819     */
1820    /* if-cmp vAA, +BBBB */
1821    mov     r0, rINST, lsr #8           @ r0<- AA
1822    GET_VREG(r2, r0)                    @ r2<- vAA
1823    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1824    cmp     r2, #0                      @ compare (vA, 0)
1825    bge  1f                      @ branch to 1 if comparison failed
1826    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1827    movs    r9, r9, asl #1              @ convert to bytes, check sign
1828    bmi     common_backwardBranch       @ backward branch, do periodic checks
18291:
1830#if defined(WITH_JIT)
1831    GET_JIT_PROF_TABLE(r0)
1832    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1833    cmp     r0,#0
1834    bne     common_updateProfile
1835    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1836    GOTO_OPCODE(ip)                     @ jump to next instruction
1837#else
1838    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1840    GOTO_OPCODE(ip)                     @ jump to next instruction
1841#endif
1842
1843
1844
1845/* ------------------------------ */
1846    .balign 64
1847.L_OP_IF_GEZ: /* 0x3b */
1848/* File: armv5te/OP_IF_GEZ.S */
1849/* File: armv5te/zcmp.S */
1850    /*
1851     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1852     * fragment that specifies the *reverse* comparison to perform, e.g.
1853     * for "if-le" you would use "gt".
1854     *
1855     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1856     */
1857    /* if-cmp vAA, +BBBB */
1858    mov     r0, rINST, lsr #8           @ r0<- AA
1859    GET_VREG(r2, r0)                    @ r2<- vAA
1860    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1861    cmp     r2, #0                      @ compare (vA, 0)
1862    blt  1f                      @ branch to 1 if comparison failed
1863    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1864    movs    r9, r9, asl #1              @ convert to bytes, check sign
1865    bmi     common_backwardBranch       @ backward branch, do periodic checks
18661:
1867#if defined(WITH_JIT)
1868    GET_JIT_PROF_TABLE(r0)
1869    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1870    cmp     r0,#0
1871    bne     common_updateProfile
1872    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1873    GOTO_OPCODE(ip)                     @ jump to next instruction
1874#else
1875    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1876    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1877    GOTO_OPCODE(ip)                     @ jump to next instruction
1878#endif
1879
1880
1881
1882/* ------------------------------ */
1883    .balign 64
1884.L_OP_IF_GTZ: /* 0x3c */
1885/* File: armv5te/OP_IF_GTZ.S */
1886/* File: armv5te/zcmp.S */
1887    /*
1888     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1889     * fragment that specifies the *reverse* comparison to perform, e.g.
1890     * for "if-le" you would use "gt".
1891     *
1892     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1893     */
1894    /* if-cmp vAA, +BBBB */
1895    mov     r0, rINST, lsr #8           @ r0<- AA
1896    GET_VREG(r2, r0)                    @ r2<- vAA
1897    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1898    cmp     r2, #0                      @ compare (vA, 0)
1899    ble  1f                      @ branch to 1 if comparison failed
1900    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1901    movs    r9, r9, asl #1              @ convert to bytes, check sign
1902    bmi     common_backwardBranch       @ backward branch, do periodic checks
19031:
1904#if defined(WITH_JIT)
1905    GET_JIT_PROF_TABLE(r0)
1906    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1907    cmp     r0,#0
1908    bne     common_updateProfile
1909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1910    GOTO_OPCODE(ip)                     @ jump to next instruction
1911#else
1912    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1913    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1914    GOTO_OPCODE(ip)                     @ jump to next instruction
1915#endif
1916
1917
1918
1919/* ------------------------------ */
1920    .balign 64
1921.L_OP_IF_LEZ: /* 0x3d */
1922/* File: armv5te/OP_IF_LEZ.S */
1923/* File: armv5te/zcmp.S */
1924    /*
1925     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1926     * fragment that specifies the *reverse* comparison to perform, e.g.
1927     * for "if-le" you would use "gt".
1928     *
1929     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1930     */
1931    /* if-cmp vAA, +BBBB */
1932    mov     r0, rINST, lsr #8           @ r0<- AA
1933    GET_VREG(r2, r0)                    @ r2<- vAA
1934    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1935    cmp     r2, #0                      @ compare (vA, 0)
1936    bgt  1f                      @ branch to 1 if comparison failed
1937    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1938    movs    r9, r9, asl #1              @ convert to bytes, check sign
1939    bmi     common_backwardBranch       @ backward branch, do periodic checks
19401:
1941#if defined(WITH_JIT)
1942    GET_JIT_PROF_TABLE(r0)
1943    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1944    cmp     r0,#0
1945    bne     common_updateProfile
1946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1947    GOTO_OPCODE(ip)                     @ jump to next instruction
1948#else
1949    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1951    GOTO_OPCODE(ip)                     @ jump to next instruction
1952#endif
1953
1954
1955
1956/* ------------------------------ */
1957    .balign 64
1958.L_OP_UNUSED_3E: /* 0x3e */
1959/* File: armv5te/OP_UNUSED_3E.S */
1960/* File: armv5te/unused.S */
1961    bl      common_abort
1962
1963
1964
1965/* ------------------------------ */
1966    .balign 64
1967.L_OP_UNUSED_3F: /* 0x3f */
1968/* File: armv5te/OP_UNUSED_3F.S */
1969/* File: armv5te/unused.S */
1970    bl      common_abort
1971
1972
1973
1974/* ------------------------------ */
1975    .balign 64
1976.L_OP_UNUSED_40: /* 0x40 */
1977/* File: armv5te/OP_UNUSED_40.S */
1978/* File: armv5te/unused.S */
1979    bl      common_abort
1980
1981
1982
1983/* ------------------------------ */
1984    .balign 64
1985.L_OP_UNUSED_41: /* 0x41 */
1986/* File: armv5te/OP_UNUSED_41.S */
1987/* File: armv5te/unused.S */
1988    bl      common_abort
1989
1990
1991
1992/* ------------------------------ */
1993    .balign 64
1994.L_OP_UNUSED_42: /* 0x42 */
1995/* File: armv5te/OP_UNUSED_42.S */
1996/* File: armv5te/unused.S */
1997    bl      common_abort
1998
1999
2000
2001/* ------------------------------ */
2002    .balign 64
2003.L_OP_UNUSED_43: /* 0x43 */
2004/* File: armv5te/OP_UNUSED_43.S */
2005/* File: armv5te/unused.S */
2006    bl      common_abort
2007
2008
2009
2010/* ------------------------------ */
2011    .balign 64
2012.L_OP_AGET: /* 0x44 */
2013/* File: armv5te/OP_AGET.S */
2014    /*
2015     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2016     *
2017     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2018     * instructions.  We use a pair of FETCH_Bs instead.
2019     *
2020     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2021     */
2022    /* op vAA, vBB, vCC */
2023    FETCH_B(r2, 1, 0)                   @ r2<- BB
2024    mov     r9, rINST, lsr #8           @ r9<- AA
2025    FETCH_B(r3, 1, 1)                   @ r3<- CC
2026    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2027    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2028    cmp     r0, #0                      @ null array object?
2029    beq     common_errNullObject        @ yes, bail
2030    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2031    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2032    cmp     r1, r3                      @ compare unsigned index, length
2033    bcs     common_errArrayIndex        @ index >= length, bail
2034    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2035    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2037    SET_VREG(r2, r9)                    @ vAA<- r2
2038    GOTO_OPCODE(ip)                     @ jump to next instruction
2039
2040
2041/* ------------------------------ */
2042    .balign 64
2043.L_OP_AGET_WIDE: /* 0x45 */
2044/* File: armv5te/OP_AGET_WIDE.S */
2045    /*
2046     * Array get, 64 bits.  vAA <- vBB[vCC].
2047     *
2048     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2049     */
2050    /* aget-wide vAA, vBB, vCC */
2051    FETCH(r0, 1)                        @ r0<- CCBB
2052    mov     r9, rINST, lsr #8           @ r9<- AA
2053    and     r2, r0, #255                @ r2<- BB
2054    mov     r3, r0, lsr #8              @ r3<- CC
2055    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2056    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2057    cmp     r0, #0                      @ null array object?
2058    beq     common_errNullObject        @ yes, bail
2059    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2060    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2061    cmp     r1, r3                      @ compare unsigned index, length
2062    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2063    b       common_errArrayIndex        @ index >= length, bail
2064    @ May want to swap the order of these two branches depending on how the
2065    @ branch prediction (if any) handles conditional forward branches vs.
2066    @ unconditional forward branches.
2067
2068/* ------------------------------ */
2069    .balign 64
2070.L_OP_AGET_OBJECT: /* 0x46 */
2071/* File: armv5te/OP_AGET_OBJECT.S */
2072/* File: armv5te/OP_AGET.S */
2073    /*
2074     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2075     *
2076     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2077     * instructions.  We use a pair of FETCH_Bs instead.
2078     *
2079     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2080     */
2081    /* op vAA, vBB, vCC */
2082    FETCH_B(r2, 1, 0)                   @ r2<- BB
2083    mov     r9, rINST, lsr #8           @ r9<- AA
2084    FETCH_B(r3, 1, 1)                   @ r3<- CC
2085    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2086    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2087    cmp     r0, #0                      @ null array object?
2088    beq     common_errNullObject        @ yes, bail
2089    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2090    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2091    cmp     r1, r3                      @ compare unsigned index, length
2092    bcs     common_errArrayIndex        @ index >= length, bail
2093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2094    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2096    SET_VREG(r2, r9)                    @ vAA<- r2
2097    GOTO_OPCODE(ip)                     @ jump to next instruction
2098
2099
2100
2101/* ------------------------------ */
2102    .balign 64
2103.L_OP_AGET_BOOLEAN: /* 0x47 */
2104/* File: armv5te/OP_AGET_BOOLEAN.S */
2105/* File: armv5te/OP_AGET.S */
2106    /*
2107     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2108     *
2109     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2110     * instructions.  We use a pair of FETCH_Bs instead.
2111     *
2112     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2113     */
2114    /* op vAA, vBB, vCC */
2115    FETCH_B(r2, 1, 0)                   @ r2<- BB
2116    mov     r9, rINST, lsr #8           @ r9<- AA
2117    FETCH_B(r3, 1, 1)                   @ r3<- CC
2118    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2119    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2120    cmp     r0, #0                      @ null array object?
2121    beq     common_errNullObject        @ yes, bail
2122    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2123    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2124    cmp     r1, r3                      @ compare unsigned index, length
2125    bcs     common_errArrayIndex        @ index >= length, bail
2126    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2127    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2128    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2129    SET_VREG(r2, r9)                    @ vAA<- r2
2130    GOTO_OPCODE(ip)                     @ jump to next instruction
2131
2132
2133
2134/* ------------------------------ */
2135    .balign 64
2136.L_OP_AGET_BYTE: /* 0x48 */
2137/* File: armv5te/OP_AGET_BYTE.S */
2138/* File: armv5te/OP_AGET.S */
2139    /*
2140     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2141     *
2142     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2143     * instructions.  We use a pair of FETCH_Bs instead.
2144     *
2145     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2146     */
2147    /* op vAA, vBB, vCC */
2148    FETCH_B(r2, 1, 0)                   @ r2<- BB
2149    mov     r9, rINST, lsr #8           @ r9<- AA
2150    FETCH_B(r3, 1, 1)                   @ r3<- CC
2151    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2152    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2153    cmp     r0, #0                      @ null array object?
2154    beq     common_errNullObject        @ yes, bail
2155    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2156    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2157    cmp     r1, r3                      @ compare unsigned index, length
2158    bcs     common_errArrayIndex        @ index >= length, bail
2159    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2160    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2162    SET_VREG(r2, r9)                    @ vAA<- r2
2163    GOTO_OPCODE(ip)                     @ jump to next instruction
2164
2165
2166
2167/* ------------------------------ */
2168    .balign 64
2169.L_OP_AGET_CHAR: /* 0x49 */
2170/* File: armv5te/OP_AGET_CHAR.S */
2171/* File: armv5te/OP_AGET.S */
2172    /*
2173     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2174     *
2175     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2176     * instructions.  We use a pair of FETCH_Bs instead.
2177     *
2178     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2179     */
2180    /* op vAA, vBB, vCC */
2181    FETCH_B(r2, 1, 0)                   @ r2<- BB
2182    mov     r9, rINST, lsr #8           @ r9<- AA
2183    FETCH_B(r3, 1, 1)                   @ r3<- CC
2184    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2185    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2186    cmp     r0, #0                      @ null array object?
2187    beq     common_errNullObject        @ yes, bail
2188    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2189    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2190    cmp     r1, r3                      @ compare unsigned index, length
2191    bcs     common_errArrayIndex        @ index >= length, bail
2192    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2193    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2194    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2195    SET_VREG(r2, r9)                    @ vAA<- r2
2196    GOTO_OPCODE(ip)                     @ jump to next instruction
2197
2198
2199
2200/* ------------------------------ */
2201    .balign 64
2202.L_OP_AGET_SHORT: /* 0x4a */
2203/* File: armv5te/OP_AGET_SHORT.S */
2204/* File: armv5te/OP_AGET.S */
2205    /*
2206     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2207     *
2208     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2209     * instructions.  We use a pair of FETCH_Bs instead.
2210     *
2211     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2212     */
2213    /* op vAA, vBB, vCC */
2214    FETCH_B(r2, 1, 0)                   @ r2<- BB
2215    mov     r9, rINST, lsr #8           @ r9<- AA
2216    FETCH_B(r3, 1, 1)                   @ r3<- CC
2217    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2218    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2219    cmp     r0, #0                      @ null array object?
2220    beq     common_errNullObject        @ yes, bail
2221    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2222    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2223    cmp     r1, r3                      @ compare unsigned index, length
2224    bcs     common_errArrayIndex        @ index >= length, bail
2225    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2226    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2227    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2228    SET_VREG(r2, r9)                    @ vAA<- r2
2229    GOTO_OPCODE(ip)                     @ jump to next instruction
2230
2231
2232
2233/* ------------------------------ */
2234    .balign 64
2235.L_OP_APUT: /* 0x4b */
2236/* File: armv5te/OP_APUT.S */
2237    /*
2238     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2239     *
2240     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2241     * instructions.  We use a pair of FETCH_Bs instead.
2242     *
2243     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2244     */
2245    /* op vAA, vBB, vCC */
2246    FETCH_B(r2, 1, 0)                   @ r2<- BB
2247    mov     r9, rINST, lsr #8           @ r9<- AA
2248    FETCH_B(r3, 1, 1)                   @ r3<- CC
2249    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2250    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2251    cmp     r0, #0                      @ null array object?
2252    beq     common_errNullObject        @ yes, bail
2253    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2254    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2255    cmp     r1, r3                      @ compare unsigned index, length
2256    bcs     common_errArrayIndex        @ index >= length, bail
2257    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2258    GET_VREG(r2, r9)                    @ r2<- vAA
2259    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2260    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2261    GOTO_OPCODE(ip)                     @ jump to next instruction
2262
2263
2264/* ------------------------------ */
2265    .balign 64
2266.L_OP_APUT_WIDE: /* 0x4c */
2267/* File: armv5te/OP_APUT_WIDE.S */
2268    /*
2269     * Array put, 64 bits.  vBB[vCC] <- vAA.
2270     *
2271     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2272     */
2273    /* aput-wide vAA, vBB, vCC */
2274    FETCH(r0, 1)                        @ r0<- CCBB
2275    mov     r9, rINST, lsr #8           @ r9<- AA
2276    and     r2, r0, #255                @ r2<- BB
2277    mov     r3, r0, lsr #8              @ r3<- CC
2278    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2279    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2280    cmp     r0, #0                      @ null array object?
2281    beq     common_errNullObject        @ yes, bail
2282    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2283    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2284    cmp     r1, r3                      @ compare unsigned index, length
2285    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2286    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2287    b       common_errArrayIndex        @ index >= length, bail
2288    @ May want to swap the order of these two branches depending on how the
2289    @ branch prediction (if any) handles conditional forward branches vs.
2290    @ unconditional forward branches.
2291
2292/* ------------------------------ */
2293    .balign 64
2294.L_OP_APUT_OBJECT: /* 0x4d */
2295/* File: armv5te/OP_APUT_OBJECT.S */
2296    /*
2297     * Store an object into an array.  vBB[vCC] <- vAA.
2298     *
2299     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2300     * instructions.  We use a pair of FETCH_Bs instead.
2301     */
2302    /* op vAA, vBB, vCC */
2303    FETCH(r0, 1)                        @ r0<- CCBB
2304    mov     r9, rINST, lsr #8           @ r9<- AA
2305    and     r2, r0, #255                @ r2<- BB
2306    mov     r3, r0, lsr #8              @ r3<- CC
2307    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2308    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2309    cmp     r1, #0                      @ null array object?
2310    GET_VREG(r9, r9)                    @ r9<- vAA
2311    beq     common_errNullObject        @ yes, bail
2312    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2313    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2314    cmp     r0, r3                      @ compare unsigned index, length
2315    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2316    b       common_errArrayIndex        @ index >= length, bail
2317
2318
2319/* ------------------------------ */
2320    .balign 64
2321.L_OP_APUT_BOOLEAN: /* 0x4e */
2322/* File: armv5te/OP_APUT_BOOLEAN.S */
2323/* File: armv5te/OP_APUT.S */
2324    /*
2325     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2326     *
2327     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2328     * instructions.  We use a pair of FETCH_Bs instead.
2329     *
2330     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2331     */
2332    /* op vAA, vBB, vCC */
2333    FETCH_B(r2, 1, 0)                   @ r2<- BB
2334    mov     r9, rINST, lsr #8           @ r9<- AA
2335    FETCH_B(r3, 1, 1)                   @ r3<- CC
2336    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2337    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2338    cmp     r0, #0                      @ null array object?
2339    beq     common_errNullObject        @ yes, bail
2340    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2341    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2342    cmp     r1, r3                      @ compare unsigned index, length
2343    bcs     common_errArrayIndex        @ index >= length, bail
2344    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2345    GET_VREG(r2, r9)                    @ r2<- vAA
2346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2347    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2348    GOTO_OPCODE(ip)                     @ jump to next instruction
2349
2350
2351
2352/* ------------------------------ */
2353    .balign 64
2354.L_OP_APUT_BYTE: /* 0x4f */
2355/* File: armv5te/OP_APUT_BYTE.S */
2356/* File: armv5te/OP_APUT.S */
2357    /*
2358     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2359     *
2360     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2361     * instructions.  We use a pair of FETCH_Bs instead.
2362     *
2363     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2364     */
2365    /* op vAA, vBB, vCC */
2366    FETCH_B(r2, 1, 0)                   @ r2<- BB
2367    mov     r9, rINST, lsr #8           @ r9<- AA
2368    FETCH_B(r3, 1, 1)                   @ r3<- CC
2369    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2370    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2371    cmp     r0, #0                      @ null array object?
2372    beq     common_errNullObject        @ yes, bail
2373    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2374    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2375    cmp     r1, r3                      @ compare unsigned index, length
2376    bcs     common_errArrayIndex        @ index >= length, bail
2377    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2378    GET_VREG(r2, r9)                    @ r2<- vAA
2379    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2380    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2381    GOTO_OPCODE(ip)                     @ jump to next instruction
2382
2383
2384
2385/* ------------------------------ */
2386    .balign 64
2387.L_OP_APUT_CHAR: /* 0x50 */
2388/* File: armv5te/OP_APUT_CHAR.S */
2389/* File: armv5te/OP_APUT.S */
2390    /*
2391     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2392     *
2393     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2394     * instructions.  We use a pair of FETCH_Bs instead.
2395     *
2396     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2397     */
2398    /* op vAA, vBB, vCC */
2399    FETCH_B(r2, 1, 0)                   @ r2<- BB
2400    mov     r9, rINST, lsr #8           @ r9<- AA
2401    FETCH_B(r3, 1, 1)                   @ r3<- CC
2402    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2403    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2404    cmp     r0, #0                      @ null array object?
2405    beq     common_errNullObject        @ yes, bail
2406    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2407    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2408    cmp     r1, r3                      @ compare unsigned index, length
2409    bcs     common_errArrayIndex        @ index >= length, bail
2410    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2411    GET_VREG(r2, r9)                    @ r2<- vAA
2412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2413    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2414    GOTO_OPCODE(ip)                     @ jump to next instruction
2415
2416
2417
2418/* ------------------------------ */
2419    .balign 64
2420.L_OP_APUT_SHORT: /* 0x51 */
2421/* File: armv5te/OP_APUT_SHORT.S */
2422/* File: armv5te/OP_APUT.S */
2423    /*
2424     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2425     *
2426     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2427     * instructions.  We use a pair of FETCH_Bs instead.
2428     *
2429     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2430     */
2431    /* op vAA, vBB, vCC */
2432    FETCH_B(r2, 1, 0)                   @ r2<- BB
2433    mov     r9, rINST, lsr #8           @ r9<- AA
2434    FETCH_B(r3, 1, 1)                   @ r3<- CC
2435    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2436    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2437    cmp     r0, #0                      @ null array object?
2438    beq     common_errNullObject        @ yes, bail
2439    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2440    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2441    cmp     r1, r3                      @ compare unsigned index, length
2442    bcs     common_errArrayIndex        @ index >= length, bail
2443    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2444    GET_VREG(r2, r9)                    @ r2<- vAA
2445    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2446    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2447    GOTO_OPCODE(ip)                     @ jump to next instruction
2448
2449
2450
2451/* ------------------------------ */
2452    .balign 64
2453.L_OP_IGET: /* 0x52 */
2454/* File: armv5te/OP_IGET.S */
2455    /*
2456     * General 32-bit instance field get.
2457     *
2458     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2459     */
2460    /* op vA, vB, field@CCCC */
2461    mov     r0, rINST, lsr #12          @ r0<- B
2462    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2463    FETCH(r1, 1)                        @ r1<- field ref CCCC
2464    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2465    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2466    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2467    cmp     r0, #0                      @ is resolved entry null?
2468    bne     .LOP_IGET_finish          @ no, already resolved
24698:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2470    EXPORT_PC()                         @ resolve() could throw
2471    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2472    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2473    cmp     r0, #0
2474    bne     .LOP_IGET_finish
2475    b       common_exceptionThrown
2476
2477/* ------------------------------ */
2478    .balign 64
2479.L_OP_IGET_WIDE: /* 0x53 */
2480/* File: armv5te/OP_IGET_WIDE.S */
2481    /*
2482     * Wide 32-bit instance field get.
2483     */
2484    /* iget-wide vA, vB, field@CCCC */
2485    mov     r0, rINST, lsr #12          @ r0<- B
2486    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2487    FETCH(r1, 1)                        @ r1<- field ref CCCC
2488    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2489    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2490    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2491    cmp     r0, #0                      @ is resolved entry null?
2492    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24938:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2494    EXPORT_PC()                         @ resolve() could throw
2495    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2496    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2497    cmp     r0, #0
2498    bne     .LOP_IGET_WIDE_finish
2499    b       common_exceptionThrown
2500
2501/* ------------------------------ */
2502    .balign 64
2503.L_OP_IGET_OBJECT: /* 0x54 */
2504/* File: armv5te/OP_IGET_OBJECT.S */
2505/* File: armv5te/OP_IGET.S */
2506    /*
2507     * General 32-bit instance field get.
2508     *
2509     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2510     */
2511    /* op vA, vB, field@CCCC */
2512    mov     r0, rINST, lsr #12          @ r0<- B
2513    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2514    FETCH(r1, 1)                        @ r1<- field ref CCCC
2515    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2516    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2517    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2518    cmp     r0, #0                      @ is resolved entry null?
2519    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25208:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2521    EXPORT_PC()                         @ resolve() could throw
2522    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2523    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2524    cmp     r0, #0
2525    bne     .LOP_IGET_OBJECT_finish
2526    b       common_exceptionThrown
2527
2528
2529/* ------------------------------ */
2530    .balign 64
2531.L_OP_IGET_BOOLEAN: /* 0x55 */
2532/* File: armv5te/OP_IGET_BOOLEAN.S */
2533@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2534/* File: armv5te/OP_IGET.S */
2535    /*
2536     * General 32-bit instance field get.
2537     *
2538     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2539     */
2540    /* op vA, vB, field@CCCC */
2541    mov     r0, rINST, lsr #12          @ r0<- B
2542    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2543    FETCH(r1, 1)                        @ r1<- field ref CCCC
2544    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2545    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2546    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2547    cmp     r0, #0                      @ is resolved entry null?
2548    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25498:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2550    EXPORT_PC()                         @ resolve() could throw
2551    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2552    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2553    cmp     r0, #0
2554    bne     .LOP_IGET_BOOLEAN_finish
2555    b       common_exceptionThrown
2556
2557
2558/* ------------------------------ */
2559    .balign 64
2560.L_OP_IGET_BYTE: /* 0x56 */
2561/* File: armv5te/OP_IGET_BYTE.S */
2562@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2563/* File: armv5te/OP_IGET.S */
2564    /*
2565     * General 32-bit instance field get.
2566     *
2567     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2568     */
2569    /* op vA, vB, field@CCCC */
2570    mov     r0, rINST, lsr #12          @ r0<- B
2571    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2572    FETCH(r1, 1)                        @ r1<- field ref CCCC
2573    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2574    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2575    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2576    cmp     r0, #0                      @ is resolved entry null?
2577    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25788:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2579    EXPORT_PC()                         @ resolve() could throw
2580    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2581    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2582    cmp     r0, #0
2583    bne     .LOP_IGET_BYTE_finish
2584    b       common_exceptionThrown
2585
2586
2587/* ------------------------------ */
2588    .balign 64
2589.L_OP_IGET_CHAR: /* 0x57 */
2590/* File: armv5te/OP_IGET_CHAR.S */
2591@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2592/* File: armv5te/OP_IGET.S */
2593    /*
2594     * General 32-bit instance field get.
2595     *
2596     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2597     */
2598    /* op vA, vB, field@CCCC */
2599    mov     r0, rINST, lsr #12          @ r0<- B
2600    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2601    FETCH(r1, 1)                        @ r1<- field ref CCCC
2602    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2603    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2604    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2605    cmp     r0, #0                      @ is resolved entry null?
2606    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
26078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2608    EXPORT_PC()                         @ resolve() could throw
2609    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2610    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2611    cmp     r0, #0
2612    bne     .LOP_IGET_CHAR_finish
2613    b       common_exceptionThrown
2614
2615
2616/* ------------------------------ */
2617    .balign 64
2618.L_OP_IGET_SHORT: /* 0x58 */
2619/* File: armv5te/OP_IGET_SHORT.S */
2620@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2621/* File: armv5te/OP_IGET.S */
2622    /*
2623     * General 32-bit instance field get.
2624     *
2625     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2626     */
2627    /* op vA, vB, field@CCCC */
2628    mov     r0, rINST, lsr #12          @ r0<- B
2629    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2630    FETCH(r1, 1)                        @ r1<- field ref CCCC
2631    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2632    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2633    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2634    cmp     r0, #0                      @ is resolved entry null?
2635    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26368:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2637    EXPORT_PC()                         @ resolve() could throw
2638    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2639    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2640    cmp     r0, #0
2641    bne     .LOP_IGET_SHORT_finish
2642    b       common_exceptionThrown
2643
2644
2645/* ------------------------------ */
2646    .balign 64
2647.L_OP_IPUT: /* 0x59 */
2648/* File: armv5te/OP_IPUT.S */
2649    /*
2650     * General 32-bit instance field put.
2651     *
2652     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2653     */
2654    /* op vA, vB, field@CCCC */
2655    mov     r0, rINST, lsr #12          @ r0<- B
2656    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2657    FETCH(r1, 1)                        @ r1<- field ref CCCC
2658    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2659    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2660    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2661    cmp     r0, #0                      @ is resolved entry null?
2662    bne     .LOP_IPUT_finish          @ no, already resolved
26638:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2664    EXPORT_PC()                         @ resolve() could throw
2665    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2666    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2667    cmp     r0, #0                      @ success?
2668    bne     .LOP_IPUT_finish          @ yes, finish up
2669    b       common_exceptionThrown
2670
2671/* ------------------------------ */
2672    .balign 64
2673.L_OP_IPUT_WIDE: /* 0x5a */
2674/* File: armv5te/OP_IPUT_WIDE.S */
2675    /* iput-wide vA, vB, field@CCCC */
2676    mov     r0, rINST, lsr #12          @ r0<- B
2677    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2678    FETCH(r1, 1)                        @ r1<- field ref CCCC
2679    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2680    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2681    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2682    cmp     r0, #0                      @ is resolved entry null?
2683    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26848:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2685    EXPORT_PC()                         @ resolve() could throw
2686    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2687    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2688    cmp     r0, #0                      @ success?
2689    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2690    b       common_exceptionThrown
2691
2692/* ------------------------------ */
2693    .balign 64
2694.L_OP_IPUT_OBJECT: /* 0x5b */
2695/* File: armv5te/OP_IPUT_OBJECT.S */
2696/* File: armv5te/OP_IPUT.S */
2697    /*
2698     * General 32-bit instance field put.
2699     *
2700     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2701     */
2702    /* op vA, vB, field@CCCC */
2703    mov     r0, rINST, lsr #12          @ r0<- B
2704    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2705    FETCH(r1, 1)                        @ r1<- field ref CCCC
2706    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2707    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2708    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2709    cmp     r0, #0                      @ is resolved entry null?
2710    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
27118:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2712    EXPORT_PC()                         @ resolve() could throw
2713    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2714    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2715    cmp     r0, #0                      @ success?
2716    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2717    b       common_exceptionThrown
2718
2719
2720/* ------------------------------ */
2721    .balign 64
2722.L_OP_IPUT_BOOLEAN: /* 0x5c */
2723/* File: armv5te/OP_IPUT_BOOLEAN.S */
2724@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2725/* File: armv5te/OP_IPUT.S */
2726    /*
2727     * General 32-bit instance field put.
2728     *
2729     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2730     */
2731    /* op vA, vB, field@CCCC */
2732    mov     r0, rINST, lsr #12          @ r0<- B
2733    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2734    FETCH(r1, 1)                        @ r1<- field ref CCCC
2735    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2736    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2737    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2738    cmp     r0, #0                      @ is resolved entry null?
2739    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27408:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2741    EXPORT_PC()                         @ resolve() could throw
2742    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2743    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2744    cmp     r0, #0                      @ success?
2745    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2746    b       common_exceptionThrown
2747
2748
2749/* ------------------------------ */
2750    .balign 64
2751.L_OP_IPUT_BYTE: /* 0x5d */
2752/* File: armv5te/OP_IPUT_BYTE.S */
2753@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2754/* File: armv5te/OP_IPUT.S */
2755    /*
2756     * General 32-bit instance field put.
2757     *
2758     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2759     */
2760    /* op vA, vB, field@CCCC */
2761    mov     r0, rINST, lsr #12          @ r0<- B
2762    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2763    FETCH(r1, 1)                        @ r1<- field ref CCCC
2764    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2765    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2766    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2767    cmp     r0, #0                      @ is resolved entry null?
2768    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27698:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2770    EXPORT_PC()                         @ resolve() could throw
2771    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2772    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2773    cmp     r0, #0                      @ success?
2774    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2775    b       common_exceptionThrown
2776
2777
2778/* ------------------------------ */
2779    .balign 64
2780.L_OP_IPUT_CHAR: /* 0x5e */
2781/* File: armv5te/OP_IPUT_CHAR.S */
2782@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2783/* File: armv5te/OP_IPUT.S */
2784    /*
2785     * General 32-bit instance field put.
2786     *
2787     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2788     */
2789    /* op vA, vB, field@CCCC */
2790    mov     r0, rINST, lsr #12          @ r0<- B
2791    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2792    FETCH(r1, 1)                        @ r1<- field ref CCCC
2793    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2794    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2795    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2796    cmp     r0, #0                      @ is resolved entry null?
2797    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27988:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2799    EXPORT_PC()                         @ resolve() could throw
2800    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2801    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2802    cmp     r0, #0                      @ success?
2803    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2804    b       common_exceptionThrown
2805
2806
2807/* ------------------------------ */
2808    .balign 64
2809.L_OP_IPUT_SHORT: /* 0x5f */
2810/* File: armv5te/OP_IPUT_SHORT.S */
2811@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2812/* File: armv5te/OP_IPUT.S */
2813    /*
2814     * General 32-bit instance field put.
2815     *
2816     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2817     */
2818    /* op vA, vB, field@CCCC */
2819    mov     r0, rINST, lsr #12          @ r0<- B
2820    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2821    FETCH(r1, 1)                        @ r1<- field ref CCCC
2822    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2823    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2824    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2825    cmp     r0, #0                      @ is resolved entry null?
2826    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28278:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2828    EXPORT_PC()                         @ resolve() could throw
2829    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2830    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2831    cmp     r0, #0                      @ success?
2832    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2833    b       common_exceptionThrown
2834
2835
2836/* ------------------------------ */
2837    .balign 64
2838.L_OP_SGET: /* 0x60 */
2839/* File: armv5te/OP_SGET.S */
2840    /*
2841     * General 32-bit SGET handler.
2842     *
2843     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2844     */
2845    /* op vAA, field@BBBB */
2846    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2847    FETCH(r1, 1)                        @ r1<- field ref BBBB
2848    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2849    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2850    cmp     r0, #0                      @ is resolved entry null?
2851    beq     .LOP_SGET_resolve         @ yes, do resolve
2852.LOP_SGET_finish: @ field ptr in r0
2853    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2854    mov     r2, rINST, lsr #8           @ r2<- AA
2855    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2856    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2857    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2858    GOTO_OPCODE(ip)                     @ jump to next instruction
2859
2860/* ------------------------------ */
2861    .balign 64
2862.L_OP_SGET_WIDE: /* 0x61 */
2863/* File: armv5te/OP_SGET_WIDE.S */
2864    /*
2865     * 64-bit SGET handler.
2866     */
2867    /* sget-wide vAA, field@BBBB */
2868    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2869    FETCH(r1, 1)                        @ r1<- field ref BBBB
2870    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2871    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2872    cmp     r0, #0                      @ is resolved entry null?
2873    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2874.LOP_SGET_WIDE_finish:
2875    mov     r9, rINST, lsr #8           @ r9<- AA
2876    .if 0
2877    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2878    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
2879    .else
2880    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2881    .endif
2882    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2883    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2884    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2886    GOTO_OPCODE(ip)                     @ jump to next instruction
2887
2888/* ------------------------------ */
2889    .balign 64
2890.L_OP_SGET_OBJECT: /* 0x62 */
2891/* File: armv5te/OP_SGET_OBJECT.S */
2892/* File: armv5te/OP_SGET.S */
2893    /*
2894     * General 32-bit SGET handler.
2895     *
2896     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2897     */
2898    /* op vAA, field@BBBB */
2899    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2900    FETCH(r1, 1)                        @ r1<- field ref BBBB
2901    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2902    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2903    cmp     r0, #0                      @ is resolved entry null?
2904    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2905.LOP_SGET_OBJECT_finish: @ field ptr in r0
2906    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2907    mov     r2, rINST, lsr #8           @ r2<- AA
2908    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2909    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2911    GOTO_OPCODE(ip)                     @ jump to next instruction
2912
2913
2914/* ------------------------------ */
2915    .balign 64
2916.L_OP_SGET_BOOLEAN: /* 0x63 */
2917/* File: armv5te/OP_SGET_BOOLEAN.S */
2918/* File: armv5te/OP_SGET.S */
2919    /*
2920     * General 32-bit SGET handler.
2921     *
2922     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2923     */
2924    /* op vAA, field@BBBB */
2925    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2926    FETCH(r1, 1)                        @ r1<- field ref BBBB
2927    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2928    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2929    cmp     r0, #0                      @ is resolved entry null?
2930    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2931.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2932    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2933    mov     r2, rINST, lsr #8           @ r2<- AA
2934    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2935    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2936    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2937    GOTO_OPCODE(ip)                     @ jump to next instruction
2938
2939
2940/* ------------------------------ */
2941    .balign 64
2942.L_OP_SGET_BYTE: /* 0x64 */
2943/* File: armv5te/OP_SGET_BYTE.S */
2944/* File: armv5te/OP_SGET.S */
2945    /*
2946     * General 32-bit SGET handler.
2947     *
2948     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2949     */
2950    /* op vAA, field@BBBB */
2951    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2952    FETCH(r1, 1)                        @ r1<- field ref BBBB
2953    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2954    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2955    cmp     r0, #0                      @ is resolved entry null?
2956    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2957.LOP_SGET_BYTE_finish: @ field ptr in r0
2958    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2959    mov     r2, rINST, lsr #8           @ r2<- AA
2960    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2961    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2962    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2963    GOTO_OPCODE(ip)                     @ jump to next instruction
2964
2965
2966/* ------------------------------ */
2967    .balign 64
2968.L_OP_SGET_CHAR: /* 0x65 */
2969/* File: armv5te/OP_SGET_CHAR.S */
2970/* File: armv5te/OP_SGET.S */
2971    /*
2972     * General 32-bit SGET handler.
2973     *
2974     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2975     */
2976    /* op vAA, field@BBBB */
2977    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2978    FETCH(r1, 1)                        @ r1<- field ref BBBB
2979    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2980    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2981    cmp     r0, #0                      @ is resolved entry null?
2982    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2983.LOP_SGET_CHAR_finish: @ field ptr in r0
2984    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2985    mov     r2, rINST, lsr #8           @ r2<- AA
2986    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2987    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2989    GOTO_OPCODE(ip)                     @ jump to next instruction
2990
2991
2992/* ------------------------------ */
2993    .balign 64
2994.L_OP_SGET_SHORT: /* 0x66 */
2995/* File: armv5te/OP_SGET_SHORT.S */
2996/* File: armv5te/OP_SGET.S */
2997    /*
2998     * General 32-bit SGET handler.
2999     *
3000     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
3001     */
3002    /* op vAA, field@BBBB */
3003    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3004    FETCH(r1, 1)                        @ r1<- field ref BBBB
3005    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3006    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3007    cmp     r0, #0                      @ is resolved entry null?
3008    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
3009.LOP_SGET_SHORT_finish: @ field ptr in r0
3010    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
3011    mov     r2, rINST, lsr #8           @ r2<- AA
3012    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3013    SET_VREG(r1, r2)                    @ fp[AA]<- r1
3014    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3015    GOTO_OPCODE(ip)                     @ jump to next instruction
3016
3017
3018/* ------------------------------ */
3019    .balign 64
3020.L_OP_SPUT: /* 0x67 */
3021/* File: armv5te/OP_SPUT.S */
3022    /*
3023     * General 32-bit SPUT handler.
3024     *
3025     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3026     */
3027    /* op vAA, field@BBBB */
3028    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3029    FETCH(r1, 1)                        @ r1<- field ref BBBB
3030    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3031    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3032    cmp     r0, #0                      @ is resolved entry null?
3033    beq     .LOP_SPUT_resolve         @ yes, do resolve
3034.LOP_SPUT_finish:   @ field ptr in r0
3035    mov     r2, rINST, lsr #8           @ r2<- AA
3036    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3037    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3038    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3039    str     r1, [r0, #offStaticField_value] @ field<- vAA
3040    GOTO_OPCODE(ip)                     @ jump to next instruction
3041
3042/* ------------------------------ */
3043    .balign 64
3044.L_OP_SPUT_WIDE: /* 0x68 */
3045/* File: armv5te/OP_SPUT_WIDE.S */
3046    /*
3047     * 64-bit SPUT handler.
3048     */
3049    /* sput-wide vAA, field@BBBB */
3050    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3051    FETCH(r1, 1)                        @ r1<- field ref BBBB
3052    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3053    mov     r9, rINST, lsr #8           @ r9<- AA
3054    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3055    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3056    cmp     r2, #0                      @ is resolved entry null?
3057    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3058.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3059    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3060    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3061    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3062    .if 0
3063    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3064    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
3065    .else
3066    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3067    .endif
3068    GOTO_OPCODE(r10)                    @ jump to next instruction
3069
3070/* ------------------------------ */
3071    .balign 64
3072.L_OP_SPUT_OBJECT: /* 0x69 */
3073/* File: armv5te/OP_SPUT_OBJECT.S */
3074/* File: armv5te/OP_SPUT.S */
3075    /*
3076     * General 32-bit SPUT handler.
3077     *
3078     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3079     */
3080    /* op vAA, field@BBBB */
3081    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3082    FETCH(r1, 1)                        @ r1<- field ref BBBB
3083    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3084    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3085    cmp     r0, #0                      @ is resolved entry null?
3086    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3087.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3088    mov     r2, rINST, lsr #8           @ r2<- AA
3089    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3090    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3091    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3092    str     r1, [r0, #offStaticField_value] @ field<- vAA
3093    GOTO_OPCODE(ip)                     @ jump to next instruction
3094
3095
3096/* ------------------------------ */
3097    .balign 64
3098.L_OP_SPUT_BOOLEAN: /* 0x6a */
3099/* File: armv5te/OP_SPUT_BOOLEAN.S */
3100/* File: armv5te/OP_SPUT.S */
3101    /*
3102     * General 32-bit SPUT handler.
3103     *
3104     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3105     */
3106    /* op vAA, field@BBBB */
3107    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3108    FETCH(r1, 1)                        @ r1<- field ref BBBB
3109    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3110    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3111    cmp     r0, #0                      @ is resolved entry null?
3112    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3113.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3114    mov     r2, rINST, lsr #8           @ r2<- AA
3115    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3116    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3117    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3118    str     r1, [r0, #offStaticField_value] @ field<- vAA
3119    GOTO_OPCODE(ip)                     @ jump to next instruction
3120
3121
3122/* ------------------------------ */
3123    .balign 64
3124.L_OP_SPUT_BYTE: /* 0x6b */
3125/* File: armv5te/OP_SPUT_BYTE.S */
3126/* File: armv5te/OP_SPUT.S */
3127    /*
3128     * General 32-bit SPUT handler.
3129     *
3130     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3131     */
3132    /* op vAA, field@BBBB */
3133    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3134    FETCH(r1, 1)                        @ r1<- field ref BBBB
3135    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3136    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3137    cmp     r0, #0                      @ is resolved entry null?
3138    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3139.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3140    mov     r2, rINST, lsr #8           @ r2<- AA
3141    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3142    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3144    str     r1, [r0, #offStaticField_value] @ field<- vAA
3145    GOTO_OPCODE(ip)                     @ jump to next instruction
3146
3147
3148/* ------------------------------ */
3149    .balign 64
3150.L_OP_SPUT_CHAR: /* 0x6c */
3151/* File: armv5te/OP_SPUT_CHAR.S */
3152/* File: armv5te/OP_SPUT.S */
3153    /*
3154     * General 32-bit SPUT handler.
3155     *
3156     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3157     */
3158    /* op vAA, field@BBBB */
3159    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3160    FETCH(r1, 1)                        @ r1<- field ref BBBB
3161    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3162    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3163    cmp     r0, #0                      @ is resolved entry null?
3164    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3165.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3166    mov     r2, rINST, lsr #8           @ r2<- AA
3167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3168    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3170    str     r1, [r0, #offStaticField_value] @ field<- vAA
3171    GOTO_OPCODE(ip)                     @ jump to next instruction
3172
3173
3174/* ------------------------------ */
3175    .balign 64
3176.L_OP_SPUT_SHORT: /* 0x6d */
3177/* File: armv5te/OP_SPUT_SHORT.S */
3178/* File: armv5te/OP_SPUT.S */
3179    /*
3180     * General 32-bit SPUT handler.
3181     *
3182     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3183     */
3184    /* op vAA, field@BBBB */
3185    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3186    FETCH(r1, 1)                        @ r1<- field ref BBBB
3187    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3188    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3189    cmp     r0, #0                      @ is resolved entry null?
3190    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3191.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3192    mov     r2, rINST, lsr #8           @ r2<- AA
3193    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3194    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3195    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3196    str     r1, [r0, #offStaticField_value] @ field<- vAA
3197    GOTO_OPCODE(ip)                     @ jump to next instruction
3198
3199
3200/* ------------------------------ */
3201    .balign 64
3202.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3203/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3204    /*
3205     * Handle a virtual method call.
3206     *
3207     * for: invoke-virtual, invoke-virtual/range
3208     */
3209    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3210    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3211    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3212    FETCH(r1, 1)                        @ r1<- BBBB
3213    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3214    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3215    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3216    .if     (!0)
3217    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3218    .endif
3219    cmp     r0, #0                      @ already resolved?
3220    EXPORT_PC()                         @ must export for invoke
3221    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3222    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3223    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3224    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3225    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3226    cmp     r0, #0                      @ got null?
3227    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3228    b       common_exceptionThrown      @ yes, handle exception
3229
3230/* ------------------------------ */
3231    .balign 64
3232.L_OP_INVOKE_SUPER: /* 0x6f */
3233/* File: armv5te/OP_INVOKE_SUPER.S */
3234    /*
3235     * Handle a "super" method call.
3236     *
3237     * for: invoke-super, invoke-super/range
3238     */
3239    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3240    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3241    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3242    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3243    .if     (!0)
3244    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3245    .endif
3246    FETCH(r1, 1)                        @ r1<- BBBB
3247    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3248    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3249    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3250    cmp     r2, #0                      @ null "this"?
3251    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3252    beq     common_errNullObject        @ null "this", throw exception
3253    cmp     r0, #0                      @ already resolved?
3254    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3255    EXPORT_PC()                         @ must export for invoke
3256    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3257    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3258
3259/* ------------------------------ */
3260    .balign 64
3261.L_OP_INVOKE_DIRECT: /* 0x70 */
3262/* File: armv5te/OP_INVOKE_DIRECT.S */
3263    /*
3264     * Handle a direct method call.
3265     *
3266     * (We could defer the "is 'this' pointer null" test to the common
3267     * method invocation code, and use a flag to indicate that static
3268     * calls don't count.  If we do this as part of copying the arguments
3269     * out we could avoiding loading the first arg twice.)
3270     *
3271     * for: invoke-direct, invoke-direct/range
3272     */
3273    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3274    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3275    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3276    FETCH(r1, 1)                        @ r1<- BBBB
3277    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3278    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3279    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3280    .if     (!0)
3281    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3282    .endif
3283    cmp     r0, #0                      @ already resolved?
3284    EXPORT_PC()                         @ must export for invoke
3285    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3286    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3287.LOP_INVOKE_DIRECT_finish:
3288    cmp     r2, #0                      @ null "this" ref?
3289    bne     common_invokeMethodNoRange   @ no, continue on
3290    b       common_errNullObject        @ yes, throw exception
3291
3292/* ------------------------------ */
3293    .balign 64
3294.L_OP_INVOKE_STATIC: /* 0x71 */
3295/* File: armv5te/OP_INVOKE_STATIC.S */
3296    /*
3297     * Handle a static method call.
3298     *
3299     * for: invoke-static, invoke-static/range
3300     */
3301    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3304    FETCH(r1, 1)                        @ r1<- BBBB
3305    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3306    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3307    cmp     r0, #0                      @ already resolved?
3308    EXPORT_PC()                         @ must export for invoke
3309    bne     common_invokeMethodNoRange @ yes, continue on
33100:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3311    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3312    mov     r2, #METHOD_STATIC          @ resolver method type
3313    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3314    cmp     r0, #0                      @ got null?
3315    bne     common_invokeMethodNoRange @ no, continue
3316    b       common_exceptionThrown      @ yes, handle exception
3317
3318
3319/* ------------------------------ */
3320    .balign 64
3321.L_OP_INVOKE_INTERFACE: /* 0x72 */
3322/* File: armv5te/OP_INVOKE_INTERFACE.S */
3323    /*
3324     * Handle an interface method call.
3325     *
3326     * for: invoke-interface, invoke-interface/range
3327     */
3328    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3329    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3330    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3331    FETCH(r1, 1)                        @ r1<- BBBB
3332    .if     (!0)
3333    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3334    .endif
3335    EXPORT_PC()                         @ must export for invoke
3336    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3337    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3338    cmp     r0, #0                      @ null obj?
3339    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3340    beq     common_errNullObject        @ yes, fail
3341    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3342    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3343    cmp     r0, #0                      @ failed?
3344    beq     common_exceptionThrown      @ yes, handle exception
3345    b       common_invokeMethodNoRange @ jump to common handler
3346
3347
3348/* ------------------------------ */
3349    .balign 64
3350.L_OP_UNUSED_73: /* 0x73 */
3351/* File: armv5te/OP_UNUSED_73.S */
3352/* File: armv5te/unused.S */
3353    bl      common_abort
3354
3355
3356
3357/* ------------------------------ */
3358    .balign 64
3359.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3360/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3361/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3362    /*
3363     * Handle a virtual method call.
3364     *
3365     * for: invoke-virtual, invoke-virtual/range
3366     */
3367    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3368    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3369    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3370    FETCH(r1, 1)                        @ r1<- BBBB
3371    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3372    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3373    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3374    .if     (!1)
3375    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3376    .endif
3377    cmp     r0, #0                      @ already resolved?
3378    EXPORT_PC()                         @ must export for invoke
3379    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3380    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3381    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3382    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3383    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3384    cmp     r0, #0                      @ got null?
3385    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3386    b       common_exceptionThrown      @ yes, handle exception
3387
3388
3389/* ------------------------------ */
3390    .balign 64
3391.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3392/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3393/* File: armv5te/OP_INVOKE_SUPER.S */
3394    /*
3395     * Handle a "super" method call.
3396     *
3397     * for: invoke-super, invoke-super/range
3398     */
3399    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3400    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3401    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3402    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3403    .if     (!1)
3404    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3405    .endif
3406    FETCH(r1, 1)                        @ r1<- BBBB
3407    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3408    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3409    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3410    cmp     r2, #0                      @ null "this"?
3411    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3412    beq     common_errNullObject        @ null "this", throw exception
3413    cmp     r0, #0                      @ already resolved?
3414    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3415    EXPORT_PC()                         @ must export for invoke
3416    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3417    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3418
3419
3420/* ------------------------------ */
3421    .balign 64
3422.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3423/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3424/* File: armv5te/OP_INVOKE_DIRECT.S */
3425    /*
3426     * Handle a direct method call.
3427     *
3428     * (We could defer the "is 'this' pointer null" test to the common
3429     * method invocation code, and use a flag to indicate that static
3430     * calls don't count.  If we do this as part of copying the arguments
3431     * out we could avoiding loading the first arg twice.)
3432     *
3433     * for: invoke-direct, invoke-direct/range
3434     */
3435    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3436    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3437    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3438    FETCH(r1, 1)                        @ r1<- BBBB
3439    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3440    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3441    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3442    .if     (!1)
3443    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3444    .endif
3445    cmp     r0, #0                      @ already resolved?
3446    EXPORT_PC()                         @ must export for invoke
3447    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3448    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3449.LOP_INVOKE_DIRECT_RANGE_finish:
3450    cmp     r2, #0                      @ null "this" ref?
3451    bne     common_invokeMethodRange   @ no, continue on
3452    b       common_errNullObject        @ yes, throw exception
3453
3454
3455/* ------------------------------ */
3456    .balign 64
3457.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3458/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3459/* File: armv5te/OP_INVOKE_STATIC.S */
3460    /*
3461     * Handle a static method call.
3462     *
3463     * for: invoke-static, invoke-static/range
3464     */
3465    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3466    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3467    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3468    FETCH(r1, 1)                        @ r1<- BBBB
3469    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3470    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3471    cmp     r0, #0                      @ already resolved?
3472    EXPORT_PC()                         @ must export for invoke
3473    bne     common_invokeMethodRange @ yes, continue on
34740:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3475    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3476    mov     r2, #METHOD_STATIC          @ resolver method type
3477    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3478    cmp     r0, #0                      @ got null?
3479    bne     common_invokeMethodRange @ no, continue
3480    b       common_exceptionThrown      @ yes, handle exception
3481
3482
3483
3484/* ------------------------------ */
3485    .balign 64
3486.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3487/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3488/* File: armv5te/OP_INVOKE_INTERFACE.S */
3489    /*
3490     * Handle an interface method call.
3491     *
3492     * for: invoke-interface, invoke-interface/range
3493     */
3494    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3495    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3496    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3497    FETCH(r1, 1)                        @ r1<- BBBB
3498    .if     (!1)
3499    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3500    .endif
3501    EXPORT_PC()                         @ must export for invoke
3502    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3503    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3504    cmp     r0, #0                      @ null obj?
3505    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3506    beq     common_errNullObject        @ yes, fail
3507    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3508    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3509    cmp     r0, #0                      @ failed?
3510    beq     common_exceptionThrown      @ yes, handle exception
3511    b       common_invokeMethodRange @ jump to common handler
3512
3513
3514
3515/* ------------------------------ */
3516    .balign 64
3517.L_OP_UNUSED_79: /* 0x79 */
3518/* File: armv5te/OP_UNUSED_79.S */
3519/* File: armv5te/unused.S */
3520    bl      common_abort
3521
3522
3523
3524/* ------------------------------ */
3525    .balign 64
3526.L_OP_UNUSED_7A: /* 0x7a */
3527/* File: armv5te/OP_UNUSED_7A.S */
3528/* File: armv5te/unused.S */
3529    bl      common_abort
3530
3531
3532
3533/* ------------------------------ */
3534    .balign 64
3535.L_OP_NEG_INT: /* 0x7b */
3536/* File: armv5te/OP_NEG_INT.S */
3537/* File: armv5te/unop.S */
3538    /*
3539     * Generic 32-bit unary operation.  Provide an "instr" line that
3540     * specifies an instruction that performs "result = op r0".
3541     * This could be an ARM instruction or a function call.
3542     *
3543     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3544     *      int-to-byte, int-to-char, int-to-short
3545     */
3546    /* unop vA, vB */
3547    mov     r3, rINST, lsr #12          @ r3<- B
3548    mov     r9, rINST, lsr #8           @ r9<- A+
3549    GET_VREG(r0, r3)                    @ r0<- vB
3550    and     r9, r9, #15
3551                               @ optional op; may set condition codes
3552    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3553    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3554    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3555    SET_VREG(r0, r9)                    @ vAA<- r0
3556    GOTO_OPCODE(ip)                     @ jump to next instruction
3557    /* 9-10 instructions */
3558
3559
3560/* ------------------------------ */
3561    .balign 64
3562.L_OP_NOT_INT: /* 0x7c */
3563/* File: armv5te/OP_NOT_INT.S */
3564/* File: armv5te/unop.S */
3565    /*
3566     * Generic 32-bit unary operation.  Provide an "instr" line that
3567     * specifies an instruction that performs "result = op r0".
3568     * This could be an ARM instruction or a function call.
3569     *
3570     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3571     *      int-to-byte, int-to-char, int-to-short
3572     */
3573    /* unop vA, vB */
3574    mov     r3, rINST, lsr #12          @ r3<- B
3575    mov     r9, rINST, lsr #8           @ r9<- A+
3576    GET_VREG(r0, r3)                    @ r0<- vB
3577    and     r9, r9, #15
3578                               @ optional op; may set condition codes
3579    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3580    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3582    SET_VREG(r0, r9)                    @ vAA<- r0
3583    GOTO_OPCODE(ip)                     @ jump to next instruction
3584    /* 9-10 instructions */
3585
3586
3587/* ------------------------------ */
3588    .balign 64
3589.L_OP_NEG_LONG: /* 0x7d */
3590/* File: armv5te/OP_NEG_LONG.S */
3591/* File: armv5te/unopWide.S */
3592    /*
3593     * Generic 64-bit unary operation.  Provide an "instr" line that
3594     * specifies an instruction that performs "result = op r0/r1".
3595     * This could be an ARM instruction or a function call.
3596     *
3597     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3598     */
3599    /* unop vA, vB */
3600    mov     r9, rINST, lsr #8           @ r9<- A+
3601    mov     r3, rINST, lsr #12          @ r3<- B
3602    and     r9, r9, #15
3603    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3604    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3605    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3606    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3607    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3608    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3609    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3610    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3611    GOTO_OPCODE(ip)                     @ jump to next instruction
3612    /* 12-13 instructions */
3613
3614
3615
3616/* ------------------------------ */
3617    .balign 64
3618.L_OP_NOT_LONG: /* 0x7e */
3619/* File: armv5te/OP_NOT_LONG.S */
3620/* File: armv5te/unopWide.S */
3621    /*
3622     * Generic 64-bit unary operation.  Provide an "instr" line that
3623     * specifies an instruction that performs "result = op r0/r1".
3624     * This could be an ARM instruction or a function call.
3625     *
3626     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3627     */
3628    /* unop vA, vB */
3629    mov     r9, rINST, lsr #8           @ r9<- A+
3630    mov     r3, rINST, lsr #12          @ r3<- B
3631    and     r9, r9, #15
3632    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3633    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3634    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3635    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3636    mvn     r0, r0                           @ optional op; may set condition codes
3637    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3638    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3639    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3640    GOTO_OPCODE(ip)                     @ jump to next instruction
3641    /* 12-13 instructions */
3642
3643
3644
3645/* ------------------------------ */
3646    .balign 64
3647.L_OP_NEG_FLOAT: /* 0x7f */
3648/* File: armv5te/OP_NEG_FLOAT.S */
3649/* File: armv5te/unop.S */
3650    /*
3651     * Generic 32-bit unary operation.  Provide an "instr" line that
3652     * specifies an instruction that performs "result = op r0".
3653     * This could be an ARM instruction or a function call.
3654     *
3655     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3656     *      int-to-byte, int-to-char, int-to-short
3657     */
3658    /* unop vA, vB */
3659    mov     r3, rINST, lsr #12          @ r3<- B
3660    mov     r9, rINST, lsr #8           @ r9<- A+
3661    GET_VREG(r0, r3)                    @ r0<- vB
3662    and     r9, r9, #15
3663                               @ optional op; may set condition codes
3664    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3665    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3666    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3667    SET_VREG(r0, r9)                    @ vAA<- r0
3668    GOTO_OPCODE(ip)                     @ jump to next instruction
3669    /* 9-10 instructions */
3670
3671
3672/* ------------------------------ */
3673    .balign 64
3674.L_OP_NEG_DOUBLE: /* 0x80 */
3675/* File: armv5te/OP_NEG_DOUBLE.S */
3676/* File: armv5te/unopWide.S */
3677    /*
3678     * Generic 64-bit unary operation.  Provide an "instr" line that
3679     * specifies an instruction that performs "result = op r0/r1".
3680     * This could be an ARM instruction or a function call.
3681     *
3682     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3683     */
3684    /* unop vA, vB */
3685    mov     r9, rINST, lsr #8           @ r9<- A+
3686    mov     r3, rINST, lsr #12          @ r3<- B
3687    and     r9, r9, #15
3688    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3689    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3690    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3691    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3692                               @ optional op; may set condition codes
3693    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3695    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3696    GOTO_OPCODE(ip)                     @ jump to next instruction
3697    /* 12-13 instructions */
3698
3699
3700
3701/* ------------------------------ */
3702    .balign 64
3703.L_OP_INT_TO_LONG: /* 0x81 */
3704/* File: armv5te/OP_INT_TO_LONG.S */
3705/* File: armv5te/unopWider.S */
3706    /*
3707     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3708     * that specifies an instruction that performs "result = op r0", where
3709     * "result" is a 64-bit quantity in r0/r1.
3710     *
3711     * For: int-to-long, int-to-double, float-to-long, float-to-double
3712     */
3713    /* unop vA, vB */
3714    mov     r9, rINST, lsr #8           @ r9<- A+
3715    mov     r3, rINST, lsr #12          @ r3<- B
3716    and     r9, r9, #15
3717    GET_VREG(r0, r3)                    @ r0<- vB
3718    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3719                               @ optional op; may set condition codes
3720    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3721    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3722    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3723    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3724    GOTO_OPCODE(ip)                     @ jump to next instruction
3725    /* 10-11 instructions */
3726
3727
3728/* ------------------------------ */
3729    .balign 64
3730.L_OP_INT_TO_FLOAT: /* 0x82 */
3731/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3732/* File: arm-vfp/funop.S */
3733    /*
3734     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3735     * line that specifies an instruction that performs "s1 = op s0".
3736     *
3737     * for: int-to-float, float-to-int
3738     */
3739    /* unop vA, vB */
3740    mov     r3, rINST, lsr #12          @ r3<- B
3741    mov     r9, rINST, lsr #8           @ r9<- A+
3742    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3743    flds    s0, [r3]                    @ s0<- vB
3744    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3745    and     r9, r9, #15                 @ r9<- A
3746    fsitos  s1, s0                              @ s1<- op
3747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3748    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3749    fsts    s1, [r9]                    @ vA<- s1
3750    GOTO_OPCODE(ip)                     @ jump to next instruction
3751
3752
3753/* ------------------------------ */
3754    .balign 64
3755.L_OP_INT_TO_DOUBLE: /* 0x83 */
3756/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3757/* File: arm-vfp/funopWider.S */
3758    /*
3759     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3760     * "instr" line that specifies an instruction that performs "d0 = op s0".
3761     *
3762     * For: int-to-double, float-to-double
3763     */
3764    /* unop vA, vB */
3765    mov     r3, rINST, lsr #12          @ r3<- B
3766    mov     r9, rINST, lsr #8           @ r9<- A+
3767    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3768    flds    s0, [r3]                    @ s0<- vB
3769    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3770    and     r9, r9, #15                 @ r9<- A
3771    fsitod  d0, s0                              @ d0<- op
3772    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3773    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3774    fstd    d0, [r9]                    @ vA<- d0
3775    GOTO_OPCODE(ip)                     @ jump to next instruction
3776
3777
3778/* ------------------------------ */
3779    .balign 64
3780.L_OP_LONG_TO_INT: /* 0x84 */
3781/* File: armv5te/OP_LONG_TO_INT.S */
3782/* we ignore the high word, making this equivalent to a 32-bit reg move */
3783/* File: armv5te/OP_MOVE.S */
3784    /* for move, move-object, long-to-int */
3785    /* op vA, vB */
3786    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3787    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3788    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3789    GET_VREG(r2, r1)                    @ r2<- fp[B]
3790    and     r0, r0, #15
3791    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3792    SET_VREG(r2, r0)                    @ fp[A]<- r2
3793    GOTO_OPCODE(ip)                     @ execute next instruction
3794
3795
3796
3797/* ------------------------------ */
3798    .balign 64
3799.L_OP_LONG_TO_FLOAT: /* 0x85 */
3800/* File: armv5te/OP_LONG_TO_FLOAT.S */
3801/* File: armv5te/unopNarrower.S */
3802    /*
3803     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3804     * that specifies an instruction that performs "result = op r0/r1", where
3805     * "result" is a 32-bit quantity in r0.
3806     *
3807     * For: long-to-float, double-to-int, double-to-float
3808     *
3809     * (This would work for long-to-int, but that instruction is actually
3810     * an exact match for OP_MOVE.)
3811     */
3812    /* unop vA, vB */
3813    mov     r3, rINST, lsr #12          @ r3<- B
3814    mov     r9, rINST, lsr #8           @ r9<- A+
3815    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3816    and     r9, r9, #15
3817    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3818    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3819                               @ optional op; may set condition codes
3820    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3822    SET_VREG(r0, r9)                    @ vA<- r0
3823    GOTO_OPCODE(ip)                     @ jump to next instruction
3824    /* 10-11 instructions */
3825
3826
3827/* ------------------------------ */
3828    .balign 64
3829.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3830/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3831/* File: armv5te/unopWide.S */
3832    /*
3833     * Generic 64-bit unary operation.  Provide an "instr" line that
3834     * specifies an instruction that performs "result = op r0/r1".
3835     * This could be an ARM instruction or a function call.
3836     *
3837     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3838     */
3839    /* unop vA, vB */
3840    mov     r9, rINST, lsr #8           @ r9<- A+
3841    mov     r3, rINST, lsr #12          @ r3<- B
3842    and     r9, r9, #15
3843    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3844    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3845    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3846    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3847                               @ optional op; may set condition codes
3848    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3849    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3850    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3851    GOTO_OPCODE(ip)                     @ jump to next instruction
3852    /* 12-13 instructions */
3853
3854
3855
3856/* ------------------------------ */
3857    .balign 64
3858.L_OP_FLOAT_TO_INT: /* 0x87 */
3859/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3860/* File: arm-vfp/funop.S */
3861    /*
3862     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3863     * line that specifies an instruction that performs "s1 = op s0".
3864     *
3865     * for: int-to-float, float-to-int
3866     */
3867    /* unop vA, vB */
3868    mov     r3, rINST, lsr #12          @ r3<- B
3869    mov     r9, rINST, lsr #8           @ r9<- A+
3870    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3871    flds    s0, [r3]                    @ s0<- vB
3872    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3873    and     r9, r9, #15                 @ r9<- A
3874    ftosizs s1, s0                              @ s1<- op
3875    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3876    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3877    fsts    s1, [r9]                    @ vA<- s1
3878    GOTO_OPCODE(ip)                     @ jump to next instruction
3879
3880
3881/* ------------------------------ */
3882    .balign 64
3883.L_OP_FLOAT_TO_LONG: /* 0x88 */
3884/* File: armv5te/OP_FLOAT_TO_LONG.S */
3885@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3886/* File: armv5te/unopWider.S */
3887    /*
3888     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3889     * that specifies an instruction that performs "result = op r0", where
3890     * "result" is a 64-bit quantity in r0/r1.
3891     *
3892     * For: int-to-long, int-to-double, float-to-long, float-to-double
3893     */
3894    /* unop vA, vB */
3895    mov     r9, rINST, lsr #8           @ r9<- A+
3896    mov     r3, rINST, lsr #12          @ r3<- B
3897    and     r9, r9, #15
3898    GET_VREG(r0, r3)                    @ r0<- vB
3899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3900                               @ optional op; may set condition codes
3901    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3902    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3904    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3905    GOTO_OPCODE(ip)                     @ jump to next instruction
3906    /* 10-11 instructions */
3907
3908
3909
3910/* ------------------------------ */
3911    .balign 64
3912.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3913/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3914/* File: arm-vfp/funopWider.S */
3915    /*
3916     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3917     * "instr" line that specifies an instruction that performs "d0 = op s0".
3918     *
3919     * For: int-to-double, float-to-double
3920     */
3921    /* unop vA, vB */
3922    mov     r3, rINST, lsr #12          @ r3<- B
3923    mov     r9, rINST, lsr #8           @ r9<- A+
3924    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3925    flds    s0, [r3]                    @ s0<- vB
3926    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3927    and     r9, r9, #15                 @ r9<- A
3928    fcvtds  d0, s0                              @ d0<- op
3929    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3930    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3931    fstd    d0, [r9]                    @ vA<- d0
3932    GOTO_OPCODE(ip)                     @ jump to next instruction
3933
3934
3935/* ------------------------------ */
3936    .balign 64
3937.L_OP_DOUBLE_TO_INT: /* 0x8a */
3938/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3939/* File: arm-vfp/funopNarrower.S */
3940    /*
3941     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3942     * "instr" line that specifies an instruction that performs "s0 = op d0".
3943     *
3944     * For: double-to-int, double-to-float
3945     */
3946    /* unop vA, vB */
3947    mov     r3, rINST, lsr #12          @ r3<- B
3948    mov     r9, rINST, lsr #8           @ r9<- A+
3949    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3950    fldd    d0, [r3]                    @ d0<- vB
3951    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3952    and     r9, r9, #15                 @ r9<- A
3953    ftosizd  s0, d0                              @ s0<- op
3954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3955    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3956    fsts    s0, [r9]                    @ vA<- s0
3957    GOTO_OPCODE(ip)                     @ jump to next instruction
3958
3959
3960/* ------------------------------ */
3961    .balign 64
3962.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3963/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3964@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3965/* File: armv5te/unopWide.S */
3966    /*
3967     * Generic 64-bit unary operation.  Provide an "instr" line that
3968     * specifies an instruction that performs "result = op r0/r1".
3969     * This could be an ARM instruction or a function call.
3970     *
3971     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3972     */
3973    /* unop vA, vB */
3974    mov     r9, rINST, lsr #8           @ r9<- A+
3975    mov     r3, rINST, lsr #12          @ r3<- B
3976    and     r9, r9, #15
3977    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3978    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3979    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3980    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3981                               @ optional op; may set condition codes
3982    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3984    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3985    GOTO_OPCODE(ip)                     @ jump to next instruction
3986    /* 12-13 instructions */
3987
3988
3989
3990
3991/* ------------------------------ */
3992    .balign 64
3993.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3994/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3995/* File: arm-vfp/funopNarrower.S */
3996    /*
3997     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3998     * "instr" line that specifies an instruction that performs "s0 = op d0".
3999     *
4000     * For: double-to-int, double-to-float
4001     */
4002    /* unop vA, vB */
4003    mov     r3, rINST, lsr #12          @ r3<- B
4004    mov     r9, rINST, lsr #8           @ r9<- A+
4005    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
4006    fldd    d0, [r3]                    @ d0<- vB
4007    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4008    and     r9, r9, #15                 @ r9<- A
4009    fcvtsd  s0, d0                              @ s0<- op
4010    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4011    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
4012    fsts    s0, [r9]                    @ vA<- s0
4013    GOTO_OPCODE(ip)                     @ jump to next instruction
4014
4015
4016/* ------------------------------ */
4017    .balign 64
4018.L_OP_INT_TO_BYTE: /* 0x8d */
4019/* File: armv5te/OP_INT_TO_BYTE.S */
4020/* File: armv5te/unop.S */
4021    /*
4022     * Generic 32-bit unary operation.  Provide an "instr" line that
4023     * specifies an instruction that performs "result = op r0".
4024     * This could be an ARM instruction or a function call.
4025     *
4026     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4027     *      int-to-byte, int-to-char, int-to-short
4028     */
4029    /* unop vA, vB */
4030    mov     r3, rINST, lsr #12          @ r3<- B
4031    mov     r9, rINST, lsr #8           @ r9<- A+
4032    GET_VREG(r0, r3)                    @ r0<- vB
4033    and     r9, r9, #15
4034    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4035    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4036    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4037    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4038    SET_VREG(r0, r9)                    @ vAA<- r0
4039    GOTO_OPCODE(ip)                     @ jump to next instruction
4040    /* 9-10 instructions */
4041
4042
4043/* ------------------------------ */
4044    .balign 64
4045.L_OP_INT_TO_CHAR: /* 0x8e */
4046/* File: armv5te/OP_INT_TO_CHAR.S */
4047/* File: armv5te/unop.S */
4048    /*
4049     * Generic 32-bit unary operation.  Provide an "instr" line that
4050     * specifies an instruction that performs "result = op r0".
4051     * This could be an ARM instruction or a function call.
4052     *
4053     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4054     *      int-to-byte, int-to-char, int-to-short
4055     */
4056    /* unop vA, vB */
4057    mov     r3, rINST, lsr #12          @ r3<- B
4058    mov     r9, rINST, lsr #8           @ r9<- A+
4059    GET_VREG(r0, r3)                    @ r0<- vB
4060    and     r9, r9, #15
4061    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4062    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4063    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4064    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4065    SET_VREG(r0, r9)                    @ vAA<- r0
4066    GOTO_OPCODE(ip)                     @ jump to next instruction
4067    /* 9-10 instructions */
4068
4069
4070/* ------------------------------ */
4071    .balign 64
4072.L_OP_INT_TO_SHORT: /* 0x8f */
4073/* File: armv5te/OP_INT_TO_SHORT.S */
4074/* File: armv5te/unop.S */
4075    /*
4076     * Generic 32-bit unary operation.  Provide an "instr" line that
4077     * specifies an instruction that performs "result = op r0".
4078     * This could be an ARM instruction or a function call.
4079     *
4080     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4081     *      int-to-byte, int-to-char, int-to-short
4082     */
4083    /* unop vA, vB */
4084    mov     r3, rINST, lsr #12          @ r3<- B
4085    mov     r9, rINST, lsr #8           @ r9<- A+
4086    GET_VREG(r0, r3)                    @ r0<- vB
4087    and     r9, r9, #15
4088    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4089    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4090    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4091    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4092    SET_VREG(r0, r9)                    @ vAA<- r0
4093    GOTO_OPCODE(ip)                     @ jump to next instruction
4094    /* 9-10 instructions */
4095
4096
4097/* ------------------------------ */
4098    .balign 64
4099.L_OP_ADD_INT: /* 0x90 */
4100/* File: armv5te/OP_ADD_INT.S */
4101/* File: armv5te/binop.S */
4102    /*
4103     * Generic 32-bit binary operation.  Provide an "instr" line that
4104     * specifies an instruction that performs "result = r0 op r1".
4105     * This could be an ARM instruction or a function call.  (If the result
4106     * comes back in a register other than r0, you can override "result".)
4107     *
4108     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4109     * vCC (r1).  Useful for integer division and modulus.  Note that we
4110     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4111     * handles it correctly.
4112     *
4113     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4114     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4115     *      mul-float, div-float, rem-float
4116     */
4117    /* binop vAA, vBB, vCC */
4118    FETCH(r0, 1)                        @ r0<- CCBB
4119    mov     r9, rINST, lsr #8           @ r9<- AA
4120    mov     r3, r0, lsr #8              @ r3<- CC
4121    and     r2, r0, #255                @ r2<- BB
4122    GET_VREG(r1, r3)                    @ r1<- vCC
4123    GET_VREG(r0, r2)                    @ r0<- vBB
4124    .if 0
4125    cmp     r1, #0                      @ is second operand zero?
4126    beq     common_errDivideByZero
4127    .endif
4128
4129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4130                               @ optional op; may set condition codes
4131    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4132    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4133    SET_VREG(r0, r9)               @ vAA<- r0
4134    GOTO_OPCODE(ip)                     @ jump to next instruction
4135    /* 11-14 instructions */
4136
4137
4138
4139/* ------------------------------ */
4140    .balign 64
4141.L_OP_SUB_INT: /* 0x91 */
4142/* File: armv5te/OP_SUB_INT.S */
4143/* File: armv5te/binop.S */
4144    /*
4145     * Generic 32-bit binary operation.  Provide an "instr" line that
4146     * specifies an instruction that performs "result = r0 op r1".
4147     * This could be an ARM instruction or a function call.  (If the result
4148     * comes back in a register other than r0, you can override "result".)
4149     *
4150     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4151     * vCC (r1).  Useful for integer division and modulus.  Note that we
4152     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4153     * handles it correctly.
4154     *
4155     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4156     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4157     *      mul-float, div-float, rem-float
4158     */
4159    /* binop vAA, vBB, vCC */
4160    FETCH(r0, 1)                        @ r0<- CCBB
4161    mov     r9, rINST, lsr #8           @ r9<- AA
4162    mov     r3, r0, lsr #8              @ r3<- CC
4163    and     r2, r0, #255                @ r2<- BB
4164    GET_VREG(r1, r3)                    @ r1<- vCC
4165    GET_VREG(r0, r2)                    @ r0<- vBB
4166    .if 0
4167    cmp     r1, #0                      @ is second operand zero?
4168    beq     common_errDivideByZero
4169    .endif
4170
4171    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4172                               @ optional op; may set condition codes
4173    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4175    SET_VREG(r0, r9)               @ vAA<- r0
4176    GOTO_OPCODE(ip)                     @ jump to next instruction
4177    /* 11-14 instructions */
4178
4179
4180
4181/* ------------------------------ */
4182    .balign 64
4183.L_OP_MUL_INT: /* 0x92 */
4184/* File: armv5te/OP_MUL_INT.S */
4185/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4186/* File: armv5te/binop.S */
4187    /*
4188     * Generic 32-bit binary operation.  Provide an "instr" line that
4189     * specifies an instruction that performs "result = r0 op r1".
4190     * This could be an ARM instruction or a function call.  (If the result
4191     * comes back in a register other than r0, you can override "result".)
4192     *
4193     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4194     * vCC (r1).  Useful for integer division and modulus.  Note that we
4195     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4196     * handles it correctly.
4197     *
4198     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4199     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4200     *      mul-float, div-float, rem-float
4201     */
4202    /* binop vAA, vBB, vCC */
4203    FETCH(r0, 1)                        @ r0<- CCBB
4204    mov     r9, rINST, lsr #8           @ r9<- AA
4205    mov     r3, r0, lsr #8              @ r3<- CC
4206    and     r2, r0, #255                @ r2<- BB
4207    GET_VREG(r1, r3)                    @ r1<- vCC
4208    GET_VREG(r0, r2)                    @ r0<- vBB
4209    .if 0
4210    cmp     r1, #0                      @ is second operand zero?
4211    beq     common_errDivideByZero
4212    .endif
4213
4214    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4215                               @ optional op; may set condition codes
4216    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4217    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4218    SET_VREG(r0, r9)               @ vAA<- r0
4219    GOTO_OPCODE(ip)                     @ jump to next instruction
4220    /* 11-14 instructions */
4221
4222
4223
4224/* ------------------------------ */
4225    .balign 64
4226.L_OP_DIV_INT: /* 0x93 */
4227/* File: armv5te/OP_DIV_INT.S */
4228/* File: armv5te/binop.S */
4229    /*
4230     * Generic 32-bit binary operation.  Provide an "instr" line that
4231     * specifies an instruction that performs "result = r0 op r1".
4232     * This could be an ARM instruction or a function call.  (If the result
4233     * comes back in a register other than r0, you can override "result".)
4234     *
4235     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4236     * vCC (r1).  Useful for integer division and modulus.  Note that we
4237     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4238     * handles it correctly.
4239     *
4240     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4241     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4242     *      mul-float, div-float, rem-float
4243     */
4244    /* binop vAA, vBB, vCC */
4245    FETCH(r0, 1)                        @ r0<- CCBB
4246    mov     r9, rINST, lsr #8           @ r9<- AA
4247    mov     r3, r0, lsr #8              @ r3<- CC
4248    and     r2, r0, #255                @ r2<- BB
4249    GET_VREG(r1, r3)                    @ r1<- vCC
4250    GET_VREG(r0, r2)                    @ r0<- vBB
4251    .if 1
4252    cmp     r1, #0                      @ is second operand zero?
4253    beq     common_errDivideByZero
4254    .endif
4255
4256    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4257                               @ optional op; may set condition codes
4258    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4259    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4260    SET_VREG(r0, r9)               @ vAA<- r0
4261    GOTO_OPCODE(ip)                     @ jump to next instruction
4262    /* 11-14 instructions */
4263
4264
4265
4266/* ------------------------------ */
4267    .balign 64
4268.L_OP_REM_INT: /* 0x94 */
4269/* File: armv5te/OP_REM_INT.S */
4270/* idivmod returns quotient in r0 and remainder in r1 */
4271/* File: armv5te/binop.S */
4272    /*
4273     * Generic 32-bit binary operation.  Provide an "instr" line that
4274     * specifies an instruction that performs "result = r0 op r1".
4275     * This could be an ARM instruction or a function call.  (If the result
4276     * comes back in a register other than r0, you can override "result".)
4277     *
4278     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4279     * vCC (r1).  Useful for integer division and modulus.  Note that we
4280     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4281     * handles it correctly.
4282     *
4283     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4284     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4285     *      mul-float, div-float, rem-float
4286     */
4287    /* binop vAA, vBB, vCC */
4288    FETCH(r0, 1)                        @ r0<- CCBB
4289    mov     r9, rINST, lsr #8           @ r9<- AA
4290    mov     r3, r0, lsr #8              @ r3<- CC
4291    and     r2, r0, #255                @ r2<- BB
4292    GET_VREG(r1, r3)                    @ r1<- vCC
4293    GET_VREG(r0, r2)                    @ r0<- vBB
4294    .if 1
4295    cmp     r1, #0                      @ is second operand zero?
4296    beq     common_errDivideByZero
4297    .endif
4298
4299    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4300                               @ optional op; may set condition codes
4301    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4303    SET_VREG(r1, r9)               @ vAA<- r1
4304    GOTO_OPCODE(ip)                     @ jump to next instruction
4305    /* 11-14 instructions */
4306
4307
4308
4309/* ------------------------------ */
4310    .balign 64
4311.L_OP_AND_INT: /* 0x95 */
4312/* File: armv5te/OP_AND_INT.S */
4313/* File: armv5te/binop.S */
4314    /*
4315     * Generic 32-bit binary operation.  Provide an "instr" line that
4316     * specifies an instruction that performs "result = r0 op r1".
4317     * This could be an ARM instruction or a function call.  (If the result
4318     * comes back in a register other than r0, you can override "result".)
4319     *
4320     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4321     * vCC (r1).  Useful for integer division and modulus.  Note that we
4322     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4323     * handles it correctly.
4324     *
4325     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4326     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4327     *      mul-float, div-float, rem-float
4328     */
4329    /* binop vAA, vBB, vCC */
4330    FETCH(r0, 1)                        @ r0<- CCBB
4331    mov     r9, rINST, lsr #8           @ r9<- AA
4332    mov     r3, r0, lsr #8              @ r3<- CC
4333    and     r2, r0, #255                @ r2<- BB
4334    GET_VREG(r1, r3)                    @ r1<- vCC
4335    GET_VREG(r0, r2)                    @ r0<- vBB
4336    .if 0
4337    cmp     r1, #0                      @ is second operand zero?
4338    beq     common_errDivideByZero
4339    .endif
4340
4341    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4342                               @ optional op; may set condition codes
4343    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4344    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4345    SET_VREG(r0, r9)               @ vAA<- r0
4346    GOTO_OPCODE(ip)                     @ jump to next instruction
4347    /* 11-14 instructions */
4348
4349
4350
4351/* ------------------------------ */
4352    .balign 64
4353.L_OP_OR_INT: /* 0x96 */
4354/* File: armv5te/OP_OR_INT.S */
4355/* File: armv5te/binop.S */
4356    /*
4357     * Generic 32-bit binary operation.  Provide an "instr" line that
4358     * specifies an instruction that performs "result = r0 op r1".
4359     * This could be an ARM instruction or a function call.  (If the result
4360     * comes back in a register other than r0, you can override "result".)
4361     *
4362     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4363     * vCC (r1).  Useful for integer division and modulus.  Note that we
4364     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4365     * handles it correctly.
4366     *
4367     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4368     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4369     *      mul-float, div-float, rem-float
4370     */
4371    /* binop vAA, vBB, vCC */
4372    FETCH(r0, 1)                        @ r0<- CCBB
4373    mov     r9, rINST, lsr #8           @ r9<- AA
4374    mov     r3, r0, lsr #8              @ r3<- CC
4375    and     r2, r0, #255                @ r2<- BB
4376    GET_VREG(r1, r3)                    @ r1<- vCC
4377    GET_VREG(r0, r2)                    @ r0<- vBB
4378    .if 0
4379    cmp     r1, #0                      @ is second operand zero?
4380    beq     common_errDivideByZero
4381    .endif
4382
4383    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4384                               @ optional op; may set condition codes
4385    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4387    SET_VREG(r0, r9)               @ vAA<- r0
4388    GOTO_OPCODE(ip)                     @ jump to next instruction
4389    /* 11-14 instructions */
4390
4391
4392
4393/* ------------------------------ */
4394    .balign 64
4395.L_OP_XOR_INT: /* 0x97 */
4396/* File: armv5te/OP_XOR_INT.S */
4397/* File: armv5te/binop.S */
4398    /*
4399     * Generic 32-bit binary operation.  Provide an "instr" line that
4400     * specifies an instruction that performs "result = r0 op r1".
4401     * This could be an ARM instruction or a function call.  (If the result
4402     * comes back in a register other than r0, you can override "result".)
4403     *
4404     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4405     * vCC (r1).  Useful for integer division and modulus.  Note that we
4406     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4407     * handles it correctly.
4408     *
4409     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4410     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4411     *      mul-float, div-float, rem-float
4412     */
4413    /* binop vAA, vBB, vCC */
4414    FETCH(r0, 1)                        @ r0<- CCBB
4415    mov     r9, rINST, lsr #8           @ r9<- AA
4416    mov     r3, r0, lsr #8              @ r3<- CC
4417    and     r2, r0, #255                @ r2<- BB
4418    GET_VREG(r1, r3)                    @ r1<- vCC
4419    GET_VREG(r0, r2)                    @ r0<- vBB
4420    .if 0
4421    cmp     r1, #0                      @ is second operand zero?
4422    beq     common_errDivideByZero
4423    .endif
4424
4425    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4426                               @ optional op; may set condition codes
4427    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4429    SET_VREG(r0, r9)               @ vAA<- r0
4430    GOTO_OPCODE(ip)                     @ jump to next instruction
4431    /* 11-14 instructions */
4432
4433
4434
4435/* ------------------------------ */
4436    .balign 64
4437.L_OP_SHL_INT: /* 0x98 */
4438/* File: armv5te/OP_SHL_INT.S */
4439/* File: armv5te/binop.S */
4440    /*
4441     * Generic 32-bit binary operation.  Provide an "instr" line that
4442     * specifies an instruction that performs "result = r0 op r1".
4443     * This could be an ARM instruction or a function call.  (If the result
4444     * comes back in a register other than r0, you can override "result".)
4445     *
4446     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4447     * vCC (r1).  Useful for integer division and modulus.  Note that we
4448     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4449     * handles it correctly.
4450     *
4451     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4452     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4453     *      mul-float, div-float, rem-float
4454     */
4455    /* binop vAA, vBB, vCC */
4456    FETCH(r0, 1)                        @ r0<- CCBB
4457    mov     r9, rINST, lsr #8           @ r9<- AA
4458    mov     r3, r0, lsr #8              @ r3<- CC
4459    and     r2, r0, #255                @ r2<- BB
4460    GET_VREG(r1, r3)                    @ r1<- vCC
4461    GET_VREG(r0, r2)                    @ r0<- vBB
4462    .if 0
4463    cmp     r1, #0                      @ is second operand zero?
4464    beq     common_errDivideByZero
4465    .endif
4466
4467    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4468    and     r1, r1, #31                           @ optional op; may set condition codes
4469    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4470    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4471    SET_VREG(r0, r9)               @ vAA<- r0
4472    GOTO_OPCODE(ip)                     @ jump to next instruction
4473    /* 11-14 instructions */
4474
4475
4476
4477/* ------------------------------ */
4478    .balign 64
4479.L_OP_SHR_INT: /* 0x99 */
4480/* File: armv5te/OP_SHR_INT.S */
4481/* File: armv5te/binop.S */
4482    /*
4483     * Generic 32-bit binary operation.  Provide an "instr" line that
4484     * specifies an instruction that performs "result = r0 op r1".
4485     * This could be an ARM instruction or a function call.  (If the result
4486     * comes back in a register other than r0, you can override "result".)
4487     *
4488     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4489     * vCC (r1).  Useful for integer division and modulus.  Note that we
4490     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4491     * handles it correctly.
4492     *
4493     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4494     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4495     *      mul-float, div-float, rem-float
4496     */
4497    /* binop vAA, vBB, vCC */
4498    FETCH(r0, 1)                        @ r0<- CCBB
4499    mov     r9, rINST, lsr #8           @ r9<- AA
4500    mov     r3, r0, lsr #8              @ r3<- CC
4501    and     r2, r0, #255                @ r2<- BB
4502    GET_VREG(r1, r3)                    @ r1<- vCC
4503    GET_VREG(r0, r2)                    @ r0<- vBB
4504    .if 0
4505    cmp     r1, #0                      @ is second operand zero?
4506    beq     common_errDivideByZero
4507    .endif
4508
4509    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4510    and     r1, r1, #31                           @ optional op; may set condition codes
4511    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4513    SET_VREG(r0, r9)               @ vAA<- r0
4514    GOTO_OPCODE(ip)                     @ jump to next instruction
4515    /* 11-14 instructions */
4516
4517
4518
4519/* ------------------------------ */
4520    .balign 64
4521.L_OP_USHR_INT: /* 0x9a */
4522/* File: armv5te/OP_USHR_INT.S */
4523/* File: armv5te/binop.S */
4524    /*
4525     * Generic 32-bit binary operation.  Provide an "instr" line that
4526     * specifies an instruction that performs "result = r0 op r1".
4527     * This could be an ARM instruction or a function call.  (If the result
4528     * comes back in a register other than r0, you can override "result".)
4529     *
4530     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4531     * vCC (r1).  Useful for integer division and modulus.  Note that we
4532     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4533     * handles it correctly.
4534     *
4535     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4536     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4537     *      mul-float, div-float, rem-float
4538     */
4539    /* binop vAA, vBB, vCC */
4540    FETCH(r0, 1)                        @ r0<- CCBB
4541    mov     r9, rINST, lsr #8           @ r9<- AA
4542    mov     r3, r0, lsr #8              @ r3<- CC
4543    and     r2, r0, #255                @ r2<- BB
4544    GET_VREG(r1, r3)                    @ r1<- vCC
4545    GET_VREG(r0, r2)                    @ r0<- vBB
4546    .if 0
4547    cmp     r1, #0                      @ is second operand zero?
4548    beq     common_errDivideByZero
4549    .endif
4550
4551    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4552    and     r1, r1, #31                           @ optional op; may set condition codes
4553    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4554    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4555    SET_VREG(r0, r9)               @ vAA<- r0
4556    GOTO_OPCODE(ip)                     @ jump to next instruction
4557    /* 11-14 instructions */
4558
4559
4560
4561/* ------------------------------ */
4562    .balign 64
4563.L_OP_ADD_LONG: /* 0x9b */
4564/* File: armv5te/OP_ADD_LONG.S */
4565/* File: armv5te/binopWide.S */
4566    /*
4567     * Generic 64-bit binary operation.  Provide an "instr" line that
4568     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4569     * This could be an ARM instruction or a function call.  (If the result
4570     * comes back in a register other than r0, you can override "result".)
4571     *
4572     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4573     * vCC (r1).  Useful for integer division and modulus.
4574     *
4575     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4576     *      xor-long, add-double, sub-double, mul-double, div-double,
4577     *      rem-double
4578     *
4579     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4580     */
4581    /* binop vAA, vBB, vCC */
4582    FETCH(r0, 1)                        @ r0<- CCBB
4583    mov     r9, rINST, lsr #8           @ r9<- AA
4584    and     r2, r0, #255                @ r2<- BB
4585    mov     r3, r0, lsr #8              @ r3<- CC
4586    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4587    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4588    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4589    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4590    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4591    .if 0
4592    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4593    beq     common_errDivideByZero
4594    .endif
4595    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4596
4597    adds    r0, r0, r2                           @ optional op; may set condition codes
4598    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4599    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4600    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4601    GOTO_OPCODE(ip)                     @ jump to next instruction
4602    /* 14-17 instructions */
4603
4604
4605
4606/* ------------------------------ */
4607    .balign 64
4608.L_OP_SUB_LONG: /* 0x9c */
4609/* File: armv5te/OP_SUB_LONG.S */
4610/* File: armv5te/binopWide.S */
4611    /*
4612     * Generic 64-bit binary operation.  Provide an "instr" line that
4613     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4614     * This could be an ARM instruction or a function call.  (If the result
4615     * comes back in a register other than r0, you can override "result".)
4616     *
4617     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4618     * vCC (r1).  Useful for integer division and modulus.
4619     *
4620     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4621     *      xor-long, add-double, sub-double, mul-double, div-double,
4622     *      rem-double
4623     *
4624     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4625     */
4626    /* binop vAA, vBB, vCC */
4627    FETCH(r0, 1)                        @ r0<- CCBB
4628    mov     r9, rINST, lsr #8           @ r9<- AA
4629    and     r2, r0, #255                @ r2<- BB
4630    mov     r3, r0, lsr #8              @ r3<- CC
4631    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4632    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4633    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4634    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4635    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4636    .if 0
4637    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4638    beq     common_errDivideByZero
4639    .endif
4640    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4641
4642    subs    r0, r0, r2                           @ optional op; may set condition codes
4643    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4645    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4646    GOTO_OPCODE(ip)                     @ jump to next instruction
4647    /* 14-17 instructions */
4648
4649
4650
4651/* ------------------------------ */
4652    .balign 64
4653.L_OP_MUL_LONG: /* 0x9d */
4654/* File: armv5te/OP_MUL_LONG.S */
4655    /*
4656     * Signed 64-bit integer multiply.
4657     *
4658     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4659     *        WX
4660     *      x YZ
4661     *  --------
4662     *     ZW ZX
4663     *  YW YX
4664     *
4665     * The low word of the result holds ZX, the high word holds
4666     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4667     * it doesn't fit in the low 64 bits.
4668     *
4669     * Unlike most ARM math operations, multiply instructions have
4670     * restrictions on using the same register more than once (Rd and Rm
4671     * cannot be the same).
4672     */
4673    /* mul-long vAA, vBB, vCC */
4674    FETCH(r0, 1)                        @ r0<- CCBB
4675    and     r2, r0, #255                @ r2<- BB
4676    mov     r3, r0, lsr #8              @ r3<- CC
4677    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4678    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4679    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4680    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4681    mul     ip, r2, r1                  @  ip<- ZxW
4682    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4683    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4684    mov     r0, rINST, lsr #8           @ r0<- AA
4685    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4686    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4687    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4688    b       .LOP_MUL_LONG_finish
4689
4690/* ------------------------------ */
4691    .balign 64
4692.L_OP_DIV_LONG: /* 0x9e */
4693/* File: armv5te/OP_DIV_LONG.S */
4694/* File: armv5te/binopWide.S */
4695    /*
4696     * Generic 64-bit binary operation.  Provide an "instr" line that
4697     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4698     * This could be an ARM instruction or a function call.  (If the result
4699     * comes back in a register other than r0, you can override "result".)
4700     *
4701     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4702     * vCC (r1).  Useful for integer division and modulus.
4703     *
4704     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4705     *      xor-long, add-double, sub-double, mul-double, div-double,
4706     *      rem-double
4707     *
4708     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4709     */
4710    /* binop vAA, vBB, vCC */
4711    FETCH(r0, 1)                        @ r0<- CCBB
4712    mov     r9, rINST, lsr #8           @ r9<- AA
4713    and     r2, r0, #255                @ r2<- BB
4714    mov     r3, r0, lsr #8              @ r3<- CC
4715    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4716    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4717    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4718    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4719    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4720    .if 1
4721    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4722    beq     common_errDivideByZero
4723    .endif
4724    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4725
4726                               @ optional op; may set condition codes
4727    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4729    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4730    GOTO_OPCODE(ip)                     @ jump to next instruction
4731    /* 14-17 instructions */
4732
4733
4734
4735/* ------------------------------ */
4736    .balign 64
4737.L_OP_REM_LONG: /* 0x9f */
4738/* File: armv5te/OP_REM_LONG.S */
4739/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4740/* File: armv5te/binopWide.S */
4741    /*
4742     * Generic 64-bit binary operation.  Provide an "instr" line that
4743     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4744     * This could be an ARM instruction or a function call.  (If the result
4745     * comes back in a register other than r0, you can override "result".)
4746     *
4747     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4748     * vCC (r1).  Useful for integer division and modulus.
4749     *
4750     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4751     *      xor-long, add-double, sub-double, mul-double, div-double,
4752     *      rem-double
4753     *
4754     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4755     */
4756    /* binop vAA, vBB, vCC */
4757    FETCH(r0, 1)                        @ r0<- CCBB
4758    mov     r9, rINST, lsr #8           @ r9<- AA
4759    and     r2, r0, #255                @ r2<- BB
4760    mov     r3, r0, lsr #8              @ r3<- CC
4761    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4762    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4763    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4764    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4765    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4766    .if 1
4767    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4768    beq     common_errDivideByZero
4769    .endif
4770    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4771
4772                               @ optional op; may set condition codes
4773    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4775    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4776    GOTO_OPCODE(ip)                     @ jump to next instruction
4777    /* 14-17 instructions */
4778
4779
4780
4781/* ------------------------------ */
4782    .balign 64
4783.L_OP_AND_LONG: /* 0xa0 */
4784/* File: armv5te/OP_AND_LONG.S */
4785/* File: armv5te/binopWide.S */
4786    /*
4787     * Generic 64-bit binary operation.  Provide an "instr" line that
4788     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4789     * This could be an ARM instruction or a function call.  (If the result
4790     * comes back in a register other than r0, you can override "result".)
4791     *
4792     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4793     * vCC (r1).  Useful for integer division and modulus.
4794     *
4795     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4796     *      xor-long, add-double, sub-double, mul-double, div-double,
4797     *      rem-double
4798     *
4799     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4800     */
4801    /* binop vAA, vBB, vCC */
4802    FETCH(r0, 1)                        @ r0<- CCBB
4803    mov     r9, rINST, lsr #8           @ r9<- AA
4804    and     r2, r0, #255                @ r2<- BB
4805    mov     r3, r0, lsr #8              @ r3<- CC
4806    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4807    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4808    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4809    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4810    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4811    .if 0
4812    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4813    beq     common_errDivideByZero
4814    .endif
4815    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4816
4817    and     r0, r0, r2                           @ optional op; may set condition codes
4818    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4819    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4820    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4821    GOTO_OPCODE(ip)                     @ jump to next instruction
4822    /* 14-17 instructions */
4823
4824
4825
4826/* ------------------------------ */
4827    .balign 64
4828.L_OP_OR_LONG: /* 0xa1 */
4829/* File: armv5te/OP_OR_LONG.S */
4830/* File: armv5te/binopWide.S */
4831    /*
4832     * Generic 64-bit binary operation.  Provide an "instr" line that
4833     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4834     * This could be an ARM instruction or a function call.  (If the result
4835     * comes back in a register other than r0, you can override "result".)
4836     *
4837     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4838     * vCC (r1).  Useful for integer division and modulus.
4839     *
4840     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4841     *      xor-long, add-double, sub-double, mul-double, div-double,
4842     *      rem-double
4843     *
4844     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4845     */
4846    /* binop vAA, vBB, vCC */
4847    FETCH(r0, 1)                        @ r0<- CCBB
4848    mov     r9, rINST, lsr #8           @ r9<- AA
4849    and     r2, r0, #255                @ r2<- BB
4850    mov     r3, r0, lsr #8              @ r3<- CC
4851    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4852    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4853    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4854    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4855    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4856    .if 0
4857    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4858    beq     common_errDivideByZero
4859    .endif
4860    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4861
4862    orr     r0, r0, r2                           @ optional op; may set condition codes
4863    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4865    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4866    GOTO_OPCODE(ip)                     @ jump to next instruction
4867    /* 14-17 instructions */
4868
4869
4870
4871/* ------------------------------ */
4872    .balign 64
4873.L_OP_XOR_LONG: /* 0xa2 */
4874/* File: armv5te/OP_XOR_LONG.S */
4875/* File: armv5te/binopWide.S */
4876    /*
4877     * Generic 64-bit binary operation.  Provide an "instr" line that
4878     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4879     * This could be an ARM instruction or a function call.  (If the result
4880     * comes back in a register other than r0, you can override "result".)
4881     *
4882     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4883     * vCC (r1).  Useful for integer division and modulus.
4884     *
4885     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4886     *      xor-long, add-double, sub-double, mul-double, div-double,
4887     *      rem-double
4888     *
4889     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4890     */
4891    /* binop vAA, vBB, vCC */
4892    FETCH(r0, 1)                        @ r0<- CCBB
4893    mov     r9, rINST, lsr #8           @ r9<- AA
4894    and     r2, r0, #255                @ r2<- BB
4895    mov     r3, r0, lsr #8              @ r3<- CC
4896    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4897    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4898    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4899    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4900    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4901    .if 0
4902    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4903    beq     common_errDivideByZero
4904    .endif
4905    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4906
4907    eor     r0, r0, r2                           @ optional op; may set condition codes
4908    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4910    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4911    GOTO_OPCODE(ip)                     @ jump to next instruction
4912    /* 14-17 instructions */
4913
4914
4915
4916/* ------------------------------ */
4917    .balign 64
4918.L_OP_SHL_LONG: /* 0xa3 */
4919/* File: armv5te/OP_SHL_LONG.S */
4920    /*
4921     * Long integer shift.  This is different from the generic 32/64-bit
4922     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4923     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4924     * 6 bits of the shift distance.
4925     */
4926    /* shl-long vAA, vBB, vCC */
4927    FETCH(r0, 1)                        @ r0<- CCBB
4928    mov     r9, rINST, lsr #8           @ r9<- AA
4929    and     r3, r0, #255                @ r3<- BB
4930    mov     r0, r0, lsr #8              @ r0<- CC
4931    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4932    GET_VREG(r2, r0)                    @ r2<- vCC
4933    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4934    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4935    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4936
4937    mov     r1, r1, asl r2              @  r1<- r1 << r2
4938    rsb     r3, r2, #32                 @  r3<- 32 - r2
4939    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4940    subs    ip, r2, #32                 @  ip<- r2 - 32
4941    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4942    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4943    b       .LOP_SHL_LONG_finish
4944
4945/* ------------------------------ */
4946    .balign 64
4947.L_OP_SHR_LONG: /* 0xa4 */
4948/* File: armv5te/OP_SHR_LONG.S */
4949    /*
4950     * Long integer shift.  This is different from the generic 32/64-bit
4951     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4952     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4953     * 6 bits of the shift distance.
4954     */
4955    /* shr-long vAA, vBB, vCC */
4956    FETCH(r0, 1)                        @ r0<- CCBB
4957    mov     r9, rINST, lsr #8           @ r9<- AA
4958    and     r3, r0, #255                @ r3<- BB
4959    mov     r0, r0, lsr #8              @ r0<- CC
4960    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4961    GET_VREG(r2, r0)                    @ r2<- vCC
4962    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4963    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4964    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4965
4966    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4967    rsb     r3, r2, #32                 @  r3<- 32 - r2
4968    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4969    subs    ip, r2, #32                 @  ip<- r2 - 32
4970    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4971    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4972    b       .LOP_SHR_LONG_finish
4973
4974/* ------------------------------ */
4975    .balign 64
4976.L_OP_USHR_LONG: /* 0xa5 */
4977/* File: armv5te/OP_USHR_LONG.S */
4978    /*
4979     * Long integer shift.  This is different from the generic 32/64-bit
4980     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4981     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4982     * 6 bits of the shift distance.
4983     */
4984    /* ushr-long vAA, vBB, vCC */
4985    FETCH(r0, 1)                        @ r0<- CCBB
4986    mov     r9, rINST, lsr #8           @ r9<- AA
4987    and     r3, r0, #255                @ r3<- BB
4988    mov     r0, r0, lsr #8              @ r0<- CC
4989    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4990    GET_VREG(r2, r0)                    @ r2<- vCC
4991    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4992    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4993    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4994
4995    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4996    rsb     r3, r2, #32                 @  r3<- 32 - r2
4997    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4998    subs    ip, r2, #32                 @  ip<- r2 - 32
4999    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5000    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5001    b       .LOP_USHR_LONG_finish
5002
5003/* ------------------------------ */
5004    .balign 64
5005.L_OP_ADD_FLOAT: /* 0xa6 */
5006/* File: arm-vfp/OP_ADD_FLOAT.S */
5007/* File: arm-vfp/fbinop.S */
5008    /*
5009     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5010     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5011     * use the "softfp" ABI, this must be an instruction, not a function call.
5012     *
5013     * For: add-float, sub-float, mul-float, div-float
5014     */
5015    /* floatop vAA, vBB, vCC */
5016    FETCH(r0, 1)                        @ r0<- CCBB
5017    mov     r9, rINST, lsr #8           @ r9<- AA
5018    mov     r3, r0, lsr #8              @ r3<- CC
5019    and     r2, r0, #255                @ r2<- BB
5020    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5021    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5022    flds    s1, [r3]                    @ s1<- vCC
5023    flds    s0, [r2]                    @ s0<- vBB
5024
5025    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5026    fadds   s2, s0, s1                              @ s2<- op
5027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5028    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5029    fsts    s2, [r9]                    @ vAA<- s2
5030    GOTO_OPCODE(ip)                     @ jump to next instruction
5031
5032
5033/* ------------------------------ */
5034    .balign 64
5035.L_OP_SUB_FLOAT: /* 0xa7 */
5036/* File: arm-vfp/OP_SUB_FLOAT.S */
5037/* File: arm-vfp/fbinop.S */
5038    /*
5039     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5040     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5041     * use the "softfp" ABI, this must be an instruction, not a function call.
5042     *
5043     * For: add-float, sub-float, mul-float, div-float
5044     */
5045    /* floatop vAA, vBB, vCC */
5046    FETCH(r0, 1)                        @ r0<- CCBB
5047    mov     r9, rINST, lsr #8           @ r9<- AA
5048    mov     r3, r0, lsr #8              @ r3<- CC
5049    and     r2, r0, #255                @ r2<- BB
5050    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5051    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5052    flds    s1, [r3]                    @ s1<- vCC
5053    flds    s0, [r2]                    @ s0<- vBB
5054
5055    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5056    fsubs   s2, s0, s1                              @ s2<- op
5057    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5058    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5059    fsts    s2, [r9]                    @ vAA<- s2
5060    GOTO_OPCODE(ip)                     @ jump to next instruction
5061
5062
5063/* ------------------------------ */
5064    .balign 64
5065.L_OP_MUL_FLOAT: /* 0xa8 */
5066/* File: arm-vfp/OP_MUL_FLOAT.S */
5067/* File: arm-vfp/fbinop.S */
5068    /*
5069     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5070     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5071     * use the "softfp" ABI, this must be an instruction, not a function call.
5072     *
5073     * For: add-float, sub-float, mul-float, div-float
5074     */
5075    /* floatop vAA, vBB, vCC */
5076    FETCH(r0, 1)                        @ r0<- CCBB
5077    mov     r9, rINST, lsr #8           @ r9<- AA
5078    mov     r3, r0, lsr #8              @ r3<- CC
5079    and     r2, r0, #255                @ r2<- BB
5080    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5081    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5082    flds    s1, [r3]                    @ s1<- vCC
5083    flds    s0, [r2]                    @ s0<- vBB
5084
5085    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5086    fmuls   s2, s0, s1                              @ s2<- op
5087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5088    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5089    fsts    s2, [r9]                    @ vAA<- s2
5090    GOTO_OPCODE(ip)                     @ jump to next instruction
5091
5092
5093/* ------------------------------ */
5094    .balign 64
5095.L_OP_DIV_FLOAT: /* 0xa9 */
5096/* File: arm-vfp/OP_DIV_FLOAT.S */
5097/* File: arm-vfp/fbinop.S */
5098    /*
5099     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5100     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5101     * use the "softfp" ABI, this must be an instruction, not a function call.
5102     *
5103     * For: add-float, sub-float, mul-float, div-float
5104     */
5105    /* floatop vAA, vBB, vCC */
5106    FETCH(r0, 1)                        @ r0<- CCBB
5107    mov     r9, rINST, lsr #8           @ r9<- AA
5108    mov     r3, r0, lsr #8              @ r3<- CC
5109    and     r2, r0, #255                @ r2<- BB
5110    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5111    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5112    flds    s1, [r3]                    @ s1<- vCC
5113    flds    s0, [r2]                    @ s0<- vBB
5114
5115    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5116    fdivs   s2, s0, s1                              @ s2<- op
5117    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5118    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5119    fsts    s2, [r9]                    @ vAA<- s2
5120    GOTO_OPCODE(ip)                     @ jump to next instruction
5121
5122
5123/* ------------------------------ */
5124    .balign 64
5125.L_OP_REM_FLOAT: /* 0xaa */
5126/* File: armv5te/OP_REM_FLOAT.S */
5127/* EABI doesn't define a float remainder function, but libm does */
5128/* File: armv5te/binop.S */
5129    /*
5130     * Generic 32-bit binary operation.  Provide an "instr" line that
5131     * specifies an instruction that performs "result = r0 op r1".
5132     * This could be an ARM instruction or a function call.  (If the result
5133     * comes back in a register other than r0, you can override "result".)
5134     *
5135     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5136     * vCC (r1).  Useful for integer division and modulus.  Note that we
5137     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5138     * handles it correctly.
5139     *
5140     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5141     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5142     *      mul-float, div-float, rem-float
5143     */
5144    /* binop vAA, vBB, vCC */
5145    FETCH(r0, 1)                        @ r0<- CCBB
5146    mov     r9, rINST, lsr #8           @ r9<- AA
5147    mov     r3, r0, lsr #8              @ r3<- CC
5148    and     r2, r0, #255                @ r2<- BB
5149    GET_VREG(r1, r3)                    @ r1<- vCC
5150    GET_VREG(r0, r2)                    @ r0<- vBB
5151    .if 0
5152    cmp     r1, #0                      @ is second operand zero?
5153    beq     common_errDivideByZero
5154    .endif
5155
5156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5157                               @ optional op; may set condition codes
5158    bl      fmodf                              @ r0<- op, r0-r3 changed
5159    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5160    SET_VREG(r0, r9)               @ vAA<- r0
5161    GOTO_OPCODE(ip)                     @ jump to next instruction
5162    /* 11-14 instructions */
5163
5164
5165
5166/* ------------------------------ */
5167    .balign 64
5168.L_OP_ADD_DOUBLE: /* 0xab */
5169/* File: arm-vfp/OP_ADD_DOUBLE.S */
5170/* File: arm-vfp/fbinopWide.S */
5171    /*
5172     * Generic 64-bit double-precision floating point binary operation.
5173     * Provide an "instr" line that specifies an instruction that performs
5174     * "d2 = d0 op d1".
5175     *
5176     * for: add-double, sub-double, mul-double, div-double
5177     */
5178    /* doubleop vAA, vBB, vCC */
5179    FETCH(r0, 1)                        @ r0<- CCBB
5180    mov     r9, rINST, lsr #8           @ r9<- AA
5181    mov     r3, r0, lsr #8              @ r3<- CC
5182    and     r2, r0, #255                @ r2<- BB
5183    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5184    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5185    fldd    d1, [r3]                    @ d1<- vCC
5186    fldd    d0, [r2]                    @ d0<- vBB
5187
5188    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5189    faddd   d2, d0, d1                              @ s2<- op
5190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5191    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5192    fstd    d2, [r9]                    @ vAA<- d2
5193    GOTO_OPCODE(ip)                     @ jump to next instruction
5194
5195
5196/* ------------------------------ */
5197    .balign 64
5198.L_OP_SUB_DOUBLE: /* 0xac */
5199/* File: arm-vfp/OP_SUB_DOUBLE.S */
5200/* File: arm-vfp/fbinopWide.S */
5201    /*
5202     * Generic 64-bit double-precision floating point binary operation.
5203     * Provide an "instr" line that specifies an instruction that performs
5204     * "d2 = d0 op d1".
5205     *
5206     * for: add-double, sub-double, mul-double, div-double
5207     */
5208    /* doubleop vAA, vBB, vCC */
5209    FETCH(r0, 1)                        @ r0<- CCBB
5210    mov     r9, rINST, lsr #8           @ r9<- AA
5211    mov     r3, r0, lsr #8              @ r3<- CC
5212    and     r2, r0, #255                @ r2<- BB
5213    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5214    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5215    fldd    d1, [r3]                    @ d1<- vCC
5216    fldd    d0, [r2]                    @ d0<- vBB
5217
5218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5219    fsubd   d2, d0, d1                              @ s2<- op
5220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5221    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5222    fstd    d2, [r9]                    @ vAA<- d2
5223    GOTO_OPCODE(ip)                     @ jump to next instruction
5224
5225
5226/* ------------------------------ */
5227    .balign 64
5228.L_OP_MUL_DOUBLE: /* 0xad */
5229/* File: arm-vfp/OP_MUL_DOUBLE.S */
5230/* File: arm-vfp/fbinopWide.S */
5231    /*
5232     * Generic 64-bit double-precision floating point binary operation.
5233     * Provide an "instr" line that specifies an instruction that performs
5234     * "d2 = d0 op d1".
5235     *
5236     * for: add-double, sub-double, mul-double, div-double
5237     */
5238    /* doubleop vAA, vBB, vCC */
5239    FETCH(r0, 1)                        @ r0<- CCBB
5240    mov     r9, rINST, lsr #8           @ r9<- AA
5241    mov     r3, r0, lsr #8              @ r3<- CC
5242    and     r2, r0, #255                @ r2<- BB
5243    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5244    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5245    fldd    d1, [r3]                    @ d1<- vCC
5246    fldd    d0, [r2]                    @ d0<- vBB
5247
5248    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5249    fmuld   d2, d0, d1                              @ s2<- op
5250    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5251    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5252    fstd    d2, [r9]                    @ vAA<- d2
5253    GOTO_OPCODE(ip)                     @ jump to next instruction
5254
5255
5256/* ------------------------------ */
5257    .balign 64
5258.L_OP_DIV_DOUBLE: /* 0xae */
5259/* File: arm-vfp/OP_DIV_DOUBLE.S */
5260/* File: arm-vfp/fbinopWide.S */
5261    /*
5262     * Generic 64-bit double-precision floating point binary operation.
5263     * Provide an "instr" line that specifies an instruction that performs
5264     * "d2 = d0 op d1".
5265     *
5266     * for: add-double, sub-double, mul-double, div-double
5267     */
5268    /* doubleop vAA, vBB, vCC */
5269    FETCH(r0, 1)                        @ r0<- CCBB
5270    mov     r9, rINST, lsr #8           @ r9<- AA
5271    mov     r3, r0, lsr #8              @ r3<- CC
5272    and     r2, r0, #255                @ r2<- BB
5273    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5274    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5275    fldd    d1, [r3]                    @ d1<- vCC
5276    fldd    d0, [r2]                    @ d0<- vBB
5277
5278    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5279    fdivd   d2, d0, d1                              @ s2<- op
5280    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5281    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5282    fstd    d2, [r9]                    @ vAA<- d2
5283    GOTO_OPCODE(ip)                     @ jump to next instruction
5284
5285
5286/* ------------------------------ */
5287    .balign 64
5288.L_OP_REM_DOUBLE: /* 0xaf */
5289/* File: armv5te/OP_REM_DOUBLE.S */
5290/* EABI doesn't define a double remainder function, but libm does */
5291/* File: armv5te/binopWide.S */
5292    /*
5293     * Generic 64-bit binary operation.  Provide an "instr" line that
5294     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5295     * This could be an ARM instruction or a function call.  (If the result
5296     * comes back in a register other than r0, you can override "result".)
5297     *
5298     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5299     * vCC (r1).  Useful for integer division and modulus.
5300     *
5301     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5302     *      xor-long, add-double, sub-double, mul-double, div-double,
5303     *      rem-double
5304     *
5305     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5306     */
5307    /* binop vAA, vBB, vCC */
5308    FETCH(r0, 1)                        @ r0<- CCBB
5309    mov     r9, rINST, lsr #8           @ r9<- AA
5310    and     r2, r0, #255                @ r2<- BB
5311    mov     r3, r0, lsr #8              @ r3<- CC
5312    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5313    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5314    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5315    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5316    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5317    .if 0
5318    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5319    beq     common_errDivideByZero
5320    .endif
5321    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5322
5323                               @ optional op; may set condition codes
5324    bl      fmod                              @ result<- op, r0-r3 changed
5325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5326    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5327    GOTO_OPCODE(ip)                     @ jump to next instruction
5328    /* 14-17 instructions */
5329
5330
5331
5332/* ------------------------------ */
5333    .balign 64
5334.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5335/* File: armv5te/OP_ADD_INT_2ADDR.S */
5336/* File: armv5te/binop2addr.S */
5337    /*
5338     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5339     * that specifies an instruction that performs "result = r0 op r1".
5340     * This could be an ARM instruction or a function call.  (If the result
5341     * comes back in a register other than r0, you can override "result".)
5342     *
5343     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5344     * vCC (r1).  Useful for integer division and modulus.
5345     *
5346     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5347     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5348     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5349     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5350     */
5351    /* binop/2addr vA, vB */
5352    mov     r9, rINST, lsr #8           @ r9<- A+
5353    mov     r3, rINST, lsr #12          @ r3<- B
5354    and     r9, r9, #15
5355    GET_VREG(r1, r3)                    @ r1<- vB
5356    GET_VREG(r0, r9)                    @ r0<- vA
5357    .if 0
5358    cmp     r1, #0                      @ is second operand zero?
5359    beq     common_errDivideByZero
5360    .endif
5361    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5362
5363                               @ optional op; may set condition codes
5364    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5365    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5366    SET_VREG(r0, r9)               @ vAA<- r0
5367    GOTO_OPCODE(ip)                     @ jump to next instruction
5368    /* 10-13 instructions */
5369
5370
5371
5372/* ------------------------------ */
5373    .balign 64
5374.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5375/* File: armv5te/OP_SUB_INT_2ADDR.S */
5376/* File: armv5te/binop2addr.S */
5377    /*
5378     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5379     * that specifies an instruction that performs "result = r0 op r1".
5380     * This could be an ARM instruction or a function call.  (If the result
5381     * comes back in a register other than r0, you can override "result".)
5382     *
5383     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5384     * vCC (r1).  Useful for integer division and modulus.
5385     *
5386     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5387     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5388     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5389     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5390     */
5391    /* binop/2addr vA, vB */
5392    mov     r9, rINST, lsr #8           @ r9<- A+
5393    mov     r3, rINST, lsr #12          @ r3<- B
5394    and     r9, r9, #15
5395    GET_VREG(r1, r3)                    @ r1<- vB
5396    GET_VREG(r0, r9)                    @ r0<- vA
5397    .if 0
5398    cmp     r1, #0                      @ is second operand zero?
5399    beq     common_errDivideByZero
5400    .endif
5401    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5402
5403                               @ optional op; may set condition codes
5404    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5406    SET_VREG(r0, r9)               @ vAA<- r0
5407    GOTO_OPCODE(ip)                     @ jump to next instruction
5408    /* 10-13 instructions */
5409
5410
5411
5412/* ------------------------------ */
5413    .balign 64
5414.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5415/* File: armv5te/OP_MUL_INT_2ADDR.S */
5416/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5417/* File: armv5te/binop2addr.S */
5418    /*
5419     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5420     * that specifies an instruction that performs "result = r0 op r1".
5421     * This could be an ARM instruction or a function call.  (If the result
5422     * comes back in a register other than r0, you can override "result".)
5423     *
5424     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5425     * vCC (r1).  Useful for integer division and modulus.
5426     *
5427     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5428     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5429     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5430     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5431     */
5432    /* binop/2addr vA, vB */
5433    mov     r9, rINST, lsr #8           @ r9<- A+
5434    mov     r3, rINST, lsr #12          @ r3<- B
5435    and     r9, r9, #15
5436    GET_VREG(r1, r3)                    @ r1<- vB
5437    GET_VREG(r0, r9)                    @ r0<- vA
5438    .if 0
5439    cmp     r1, #0                      @ is second operand zero?
5440    beq     common_errDivideByZero
5441    .endif
5442    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5443
5444                               @ optional op; may set condition codes
5445    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5446    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5447    SET_VREG(r0, r9)               @ vAA<- r0
5448    GOTO_OPCODE(ip)                     @ jump to next instruction
5449    /* 10-13 instructions */
5450
5451
5452
5453/* ------------------------------ */
5454    .balign 64
5455.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5456/* File: armv5te/OP_DIV_INT_2ADDR.S */
5457/* File: armv5te/binop2addr.S */
5458    /*
5459     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5460     * that specifies an instruction that performs "result = r0 op r1".
5461     * This could be an ARM instruction or a function call.  (If the result
5462     * comes back in a register other than r0, you can override "result".)
5463     *
5464     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5465     * vCC (r1).  Useful for integer division and modulus.
5466     *
5467     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5468     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5469     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5470     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5471     */
5472    /* binop/2addr vA, vB */
5473    mov     r9, rINST, lsr #8           @ r9<- A+
5474    mov     r3, rINST, lsr #12          @ r3<- B
5475    and     r9, r9, #15
5476    GET_VREG(r1, r3)                    @ r1<- vB
5477    GET_VREG(r0, r9)                    @ r0<- vA
5478    .if 1
5479    cmp     r1, #0                      @ is second operand zero?
5480    beq     common_errDivideByZero
5481    .endif
5482    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5483
5484                               @ optional op; may set condition codes
5485    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5486    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5487    SET_VREG(r0, r9)               @ vAA<- r0
5488    GOTO_OPCODE(ip)                     @ jump to next instruction
5489    /* 10-13 instructions */
5490
5491
5492
5493/* ------------------------------ */
5494    .balign 64
5495.L_OP_REM_INT_2ADDR: /* 0xb4 */
5496/* File: armv5te/OP_REM_INT_2ADDR.S */
5497/* idivmod returns quotient in r0 and remainder in r1 */
5498/* File: armv5te/binop2addr.S */
5499    /*
5500     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5501     * that specifies an instruction that performs "result = r0 op r1".
5502     * This could be an ARM instruction or a function call.  (If the result
5503     * comes back in a register other than r0, you can override "result".)
5504     *
5505     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5506     * vCC (r1).  Useful for integer division and modulus.
5507     *
5508     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5509     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5510     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5511     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5512     */
5513    /* binop/2addr vA, vB */
5514    mov     r9, rINST, lsr #8           @ r9<- A+
5515    mov     r3, rINST, lsr #12          @ r3<- B
5516    and     r9, r9, #15
5517    GET_VREG(r1, r3)                    @ r1<- vB
5518    GET_VREG(r0, r9)                    @ r0<- vA
5519    .if 1
5520    cmp     r1, #0                      @ is second operand zero?
5521    beq     common_errDivideByZero
5522    .endif
5523    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5524
5525                               @ optional op; may set condition codes
5526    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5527    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5528    SET_VREG(r1, r9)               @ vAA<- r1
5529    GOTO_OPCODE(ip)                     @ jump to next instruction
5530    /* 10-13 instructions */
5531
5532
5533
5534/* ------------------------------ */
5535    .balign 64
5536.L_OP_AND_INT_2ADDR: /* 0xb5 */
5537/* File: armv5te/OP_AND_INT_2ADDR.S */
5538/* File: armv5te/binop2addr.S */
5539    /*
5540     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5541     * that specifies an instruction that performs "result = r0 op r1".
5542     * This could be an ARM instruction or a function call.  (If the result
5543     * comes back in a register other than r0, you can override "result".)
5544     *
5545     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5546     * vCC (r1).  Useful for integer division and modulus.
5547     *
5548     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5549     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5550     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5551     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5552     */
5553    /* binop/2addr vA, vB */
5554    mov     r9, rINST, lsr #8           @ r9<- A+
5555    mov     r3, rINST, lsr #12          @ r3<- B
5556    and     r9, r9, #15
5557    GET_VREG(r1, r3)                    @ r1<- vB
5558    GET_VREG(r0, r9)                    @ r0<- vA
5559    .if 0
5560    cmp     r1, #0                      @ is second operand zero?
5561    beq     common_errDivideByZero
5562    .endif
5563    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5564
5565                               @ optional op; may set condition codes
5566    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5568    SET_VREG(r0, r9)               @ vAA<- r0
5569    GOTO_OPCODE(ip)                     @ jump to next instruction
5570    /* 10-13 instructions */
5571
5572
5573
5574/* ------------------------------ */
5575    .balign 64
5576.L_OP_OR_INT_2ADDR: /* 0xb6 */
5577/* File: armv5te/OP_OR_INT_2ADDR.S */
5578/* File: armv5te/binop2addr.S */
5579    /*
5580     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5581     * that specifies an instruction that performs "result = r0 op r1".
5582     * This could be an ARM instruction or a function call.  (If the result
5583     * comes back in a register other than r0, you can override "result".)
5584     *
5585     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5586     * vCC (r1).  Useful for integer division and modulus.
5587     *
5588     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5589     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5590     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5591     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5592     */
5593    /* binop/2addr vA, vB */
5594    mov     r9, rINST, lsr #8           @ r9<- A+
5595    mov     r3, rINST, lsr #12          @ r3<- B
5596    and     r9, r9, #15
5597    GET_VREG(r1, r3)                    @ r1<- vB
5598    GET_VREG(r0, r9)                    @ r0<- vA
5599    .if 0
5600    cmp     r1, #0                      @ is second operand zero?
5601    beq     common_errDivideByZero
5602    .endif
5603    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5604
5605                               @ optional op; may set condition codes
5606    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5608    SET_VREG(r0, r9)               @ vAA<- r0
5609    GOTO_OPCODE(ip)                     @ jump to next instruction
5610    /* 10-13 instructions */
5611
5612
5613
5614/* ------------------------------ */
5615    .balign 64
5616.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5617/* File: armv5te/OP_XOR_INT_2ADDR.S */
5618/* File: armv5te/binop2addr.S */
5619    /*
5620     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5621     * that specifies an instruction that performs "result = r0 op r1".
5622     * This could be an ARM instruction or a function call.  (If the result
5623     * comes back in a register other than r0, you can override "result".)
5624     *
5625     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5626     * vCC (r1).  Useful for integer division and modulus.
5627     *
5628     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5629     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5630     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5631     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5632     */
5633    /* binop/2addr vA, vB */
5634    mov     r9, rINST, lsr #8           @ r9<- A+
5635    mov     r3, rINST, lsr #12          @ r3<- B
5636    and     r9, r9, #15
5637    GET_VREG(r1, r3)                    @ r1<- vB
5638    GET_VREG(r0, r9)                    @ r0<- vA
5639    .if 0
5640    cmp     r1, #0                      @ is second operand zero?
5641    beq     common_errDivideByZero
5642    .endif
5643    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5644
5645                               @ optional op; may set condition codes
5646    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5647    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5648    SET_VREG(r0, r9)               @ vAA<- r0
5649    GOTO_OPCODE(ip)                     @ jump to next instruction
5650    /* 10-13 instructions */
5651
5652
5653
5654/* ------------------------------ */
5655    .balign 64
5656.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5657/* File: armv5te/OP_SHL_INT_2ADDR.S */
5658/* File: armv5te/binop2addr.S */
5659    /*
5660     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5661     * that specifies an instruction that performs "result = r0 op r1".
5662     * This could be an ARM instruction or a function call.  (If the result
5663     * comes back in a register other than r0, you can override "result".)
5664     *
5665     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5666     * vCC (r1).  Useful for integer division and modulus.
5667     *
5668     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5669     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5670     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5671     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5672     */
5673    /* binop/2addr vA, vB */
5674    mov     r9, rINST, lsr #8           @ r9<- A+
5675    mov     r3, rINST, lsr #12          @ r3<- B
5676    and     r9, r9, #15
5677    GET_VREG(r1, r3)                    @ r1<- vB
5678    GET_VREG(r0, r9)                    @ r0<- vA
5679    .if 0
5680    cmp     r1, #0                      @ is second operand zero?
5681    beq     common_errDivideByZero
5682    .endif
5683    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5684
5685    and     r1, r1, #31                           @ optional op; may set condition codes
5686    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5687    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5688    SET_VREG(r0, r9)               @ vAA<- r0
5689    GOTO_OPCODE(ip)                     @ jump to next instruction
5690    /* 10-13 instructions */
5691
5692
5693
5694/* ------------------------------ */
5695    .balign 64
5696.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5697/* File: armv5te/OP_SHR_INT_2ADDR.S */
5698/* File: armv5te/binop2addr.S */
5699    /*
5700     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5701     * that specifies an instruction that performs "result = r0 op r1".
5702     * This could be an ARM instruction or a function call.  (If the result
5703     * comes back in a register other than r0, you can override "result".)
5704     *
5705     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5706     * vCC (r1).  Useful for integer division and modulus.
5707     *
5708     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5709     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5710     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5711     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5712     */
5713    /* binop/2addr vA, vB */
5714    mov     r9, rINST, lsr #8           @ r9<- A+
5715    mov     r3, rINST, lsr #12          @ r3<- B
5716    and     r9, r9, #15
5717    GET_VREG(r1, r3)                    @ r1<- vB
5718    GET_VREG(r0, r9)                    @ r0<- vA
5719    .if 0
5720    cmp     r1, #0                      @ is second operand zero?
5721    beq     common_errDivideByZero
5722    .endif
5723    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5724
5725    and     r1, r1, #31                           @ optional op; may set condition codes
5726    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5728    SET_VREG(r0, r9)               @ vAA<- r0
5729    GOTO_OPCODE(ip)                     @ jump to next instruction
5730    /* 10-13 instructions */
5731
5732
5733
5734/* ------------------------------ */
5735    .balign 64
5736.L_OP_USHR_INT_2ADDR: /* 0xba */
5737/* File: armv5te/OP_USHR_INT_2ADDR.S */
5738/* File: armv5te/binop2addr.S */
5739    /*
5740     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5741     * that specifies an instruction that performs "result = r0 op r1".
5742     * This could be an ARM instruction or a function call.  (If the result
5743     * comes back in a register other than r0, you can override "result".)
5744     *
5745     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5746     * vCC (r1).  Useful for integer division and modulus.
5747     *
5748     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5749     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5750     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5751     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5752     */
5753    /* binop/2addr vA, vB */
5754    mov     r9, rINST, lsr #8           @ r9<- A+
5755    mov     r3, rINST, lsr #12          @ r3<- B
5756    and     r9, r9, #15
5757    GET_VREG(r1, r3)                    @ r1<- vB
5758    GET_VREG(r0, r9)                    @ r0<- vA
5759    .if 0
5760    cmp     r1, #0                      @ is second operand zero?
5761    beq     common_errDivideByZero
5762    .endif
5763    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5764
5765    and     r1, r1, #31                           @ optional op; may set condition codes
5766    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5767    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5768    SET_VREG(r0, r9)               @ vAA<- r0
5769    GOTO_OPCODE(ip)                     @ jump to next instruction
5770    /* 10-13 instructions */
5771
5772
5773
5774/* ------------------------------ */
5775    .balign 64
5776.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5777/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5778/* File: armv5te/binopWide2addr.S */
5779    /*
5780     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5781     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5782     * This could be an ARM instruction or a function call.  (If the result
5783     * comes back in a register other than r0, you can override "result".)
5784     *
5785     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5786     * vCC (r1).  Useful for integer division and modulus.
5787     *
5788     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5789     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5790     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5791     *      rem-double/2addr
5792     */
5793    /* binop/2addr vA, vB */
5794    mov     r9, rINST, lsr #8           @ r9<- A+
5795    mov     r1, rINST, lsr #12          @ r1<- B
5796    and     r9, r9, #15
5797    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5798    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5799    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5800    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5801    .if 0
5802    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5803    beq     common_errDivideByZero
5804    .endif
5805    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5806
5807    adds    r0, r0, r2                           @ optional op; may set condition codes
5808    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5809    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5810    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5811    GOTO_OPCODE(ip)                     @ jump to next instruction
5812    /* 12-15 instructions */
5813
5814
5815
5816/* ------------------------------ */
5817    .balign 64
5818.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5819/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5820/* File: armv5te/binopWide2addr.S */
5821    /*
5822     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5823     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5824     * This could be an ARM instruction or a function call.  (If the result
5825     * comes back in a register other than r0, you can override "result".)
5826     *
5827     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5828     * vCC (r1).  Useful for integer division and modulus.
5829     *
5830     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5831     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5832     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5833     *      rem-double/2addr
5834     */
5835    /* binop/2addr vA, vB */
5836    mov     r9, rINST, lsr #8           @ r9<- A+
5837    mov     r1, rINST, lsr #12          @ r1<- B
5838    and     r9, r9, #15
5839    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5840    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5841    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5842    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5843    .if 0
5844    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5845    beq     common_errDivideByZero
5846    .endif
5847    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5848
5849    subs    r0, r0, r2                           @ optional op; may set condition codes
5850    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5851    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5852    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5853    GOTO_OPCODE(ip)                     @ jump to next instruction
5854    /* 12-15 instructions */
5855
5856
5857
5858/* ------------------------------ */
5859    .balign 64
5860.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5861/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5862    /*
5863     * Signed 64-bit integer multiply, "/2addr" version.
5864     *
5865     * See OP_MUL_LONG for an explanation.
5866     *
5867     * We get a little tight on registers, so to avoid looking up &fp[A]
5868     * again we stuff it into rINST.
5869     */
5870    /* mul-long/2addr vA, vB */
5871    mov     r9, rINST, lsr #8           @ r9<- A+
5872    mov     r1, rINST, lsr #12          @ r1<- B
5873    and     r9, r9, #15
5874    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5875    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5876    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5877    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5878    mul     ip, r2, r1                  @  ip<- ZxW
5879    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5880    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5881    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5882    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5883    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5885    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5886    GOTO_OPCODE(ip)                     @ jump to next instruction
5887
5888
5889/* ------------------------------ */
5890    .balign 64
5891.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5892/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5893/* File: armv5te/binopWide2addr.S */
5894    /*
5895     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5896     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5897     * This could be an ARM instruction or a function call.  (If the result
5898     * comes back in a register other than r0, you can override "result".)
5899     *
5900     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5901     * vCC (r1).  Useful for integer division and modulus.
5902     *
5903     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5904     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5905     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5906     *      rem-double/2addr
5907     */
5908    /* binop/2addr vA, vB */
5909    mov     r9, rINST, lsr #8           @ r9<- A+
5910    mov     r1, rINST, lsr #12          @ r1<- B
5911    and     r9, r9, #15
5912    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5913    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5914    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5915    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5916    .if 1
5917    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5918    beq     common_errDivideByZero
5919    .endif
5920    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5921
5922                               @ optional op; may set condition codes
5923    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5925    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5926    GOTO_OPCODE(ip)                     @ jump to next instruction
5927    /* 12-15 instructions */
5928
5929
5930
5931/* ------------------------------ */
5932    .balign 64
5933.L_OP_REM_LONG_2ADDR: /* 0xbf */
5934/* File: armv5te/OP_REM_LONG_2ADDR.S */
5935/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5936/* File: armv5te/binopWide2addr.S */
5937    /*
5938     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5939     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5940     * This could be an ARM instruction or a function call.  (If the result
5941     * comes back in a register other than r0, you can override "result".)
5942     *
5943     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5944     * vCC (r1).  Useful for integer division and modulus.
5945     *
5946     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5947     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5948     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5949     *      rem-double/2addr
5950     */
5951    /* binop/2addr vA, vB */
5952    mov     r9, rINST, lsr #8           @ r9<- A+
5953    mov     r1, rINST, lsr #12          @ r1<- B
5954    and     r9, r9, #15
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 1
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                               @ optional op; may set condition codes
5966    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5968    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5969    GOTO_OPCODE(ip)                     @ jump to next instruction
5970    /* 12-15 instructions */
5971
5972
5973
5974/* ------------------------------ */
5975    .balign 64
5976.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5977/* File: armv5te/OP_AND_LONG_2ADDR.S */
5978/* File: armv5te/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     r9, rINST, lsr #8           @ r9<- A+
5995    mov     r1, rINST, lsr #12          @ r1<- B
5996    and     r9, r9, #15
5997    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5998    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5999    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6000    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6001    .if 0
6002    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6003    beq     common_errDivideByZero
6004    .endif
6005    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6006
6007    and     r0, r0, r2                           @ optional op; may set condition codes
6008    and     r1, r1, r3                              @ result<- op, r0-r3 changed
6009    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6010    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6011    GOTO_OPCODE(ip)                     @ jump to next instruction
6012    /* 12-15 instructions */
6013
6014
6015
6016/* ------------------------------ */
6017    .balign 64
6018.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6019/* File: armv5te/OP_OR_LONG_2ADDR.S */
6020/* File: armv5te/binopWide2addr.S */
6021    /*
6022     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6023     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6024     * This could be an ARM instruction or a function call.  (If the result
6025     * comes back in a register other than r0, you can override "result".)
6026     *
6027     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6028     * vCC (r1).  Useful for integer division and modulus.
6029     *
6030     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6031     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6032     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6033     *      rem-double/2addr
6034     */
6035    /* binop/2addr vA, vB */
6036    mov     r9, rINST, lsr #8           @ r9<- A+
6037    mov     r1, rINST, lsr #12          @ r1<- B
6038    and     r9, r9, #15
6039    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6040    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6041    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6042    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6043    .if 0
6044    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6045    beq     common_errDivideByZero
6046    .endif
6047    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6048
6049    orr     r0, r0, r2                           @ optional op; may set condition codes
6050    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6051    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6052    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6053    GOTO_OPCODE(ip)                     @ jump to next instruction
6054    /* 12-15 instructions */
6055
6056
6057
6058/* ------------------------------ */
6059    .balign 64
6060.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6061/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6062/* File: armv5te/binopWide2addr.S */
6063    /*
6064     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6065     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6066     * This could be an ARM instruction or a function call.  (If the result
6067     * comes back in a register other than r0, you can override "result".)
6068     *
6069     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6070     * vCC (r1).  Useful for integer division and modulus.
6071     *
6072     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6073     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6074     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6075     *      rem-double/2addr
6076     */
6077    /* binop/2addr vA, vB */
6078    mov     r9, rINST, lsr #8           @ r9<- A+
6079    mov     r1, rINST, lsr #12          @ r1<- B
6080    and     r9, r9, #15
6081    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6082    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6083    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6084    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6085    .if 0
6086    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6087    beq     common_errDivideByZero
6088    .endif
6089    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6090
6091    eor     r0, r0, r2                           @ optional op; may set condition codes
6092    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6093    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6094    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6095    GOTO_OPCODE(ip)                     @ jump to next instruction
6096    /* 12-15 instructions */
6097
6098
6099
6100/* ------------------------------ */
6101    .balign 64
6102.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6103/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6104    /*
6105     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6106     * 32-bit shift distance.
6107     */
6108    /* shl-long/2addr vA, vB */
6109    mov     r9, rINST, lsr #8           @ r9<- A+
6110    mov     r3, rINST, lsr #12          @ r3<- B
6111    and     r9, r9, #15
6112    GET_VREG(r2, r3)                    @ r2<- vB
6113    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6114    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6115    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6116
6117    mov     r1, r1, asl r2              @  r1<- r1 << r2
6118    rsb     r3, r2, #32                 @  r3<- 32 - r2
6119    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6120    subs    ip, r2, #32                 @  ip<- r2 - 32
6121    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6122    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6123    mov     r0, r0, asl r2              @  r0<- r0 << r2
6124    b       .LOP_SHL_LONG_2ADDR_finish
6125
6126/* ------------------------------ */
6127    .balign 64
6128.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6129/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6130    /*
6131     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6132     * 32-bit shift distance.
6133     */
6134    /* shr-long/2addr vA, vB */
6135    mov     r9, rINST, lsr #8           @ r9<- A+
6136    mov     r3, rINST, lsr #12          @ r3<- B
6137    and     r9, r9, #15
6138    GET_VREG(r2, r3)                    @ r2<- vB
6139    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6140    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6141    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6142
6143    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6144    rsb     r3, r2, #32                 @  r3<- 32 - r2
6145    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6146    subs    ip, r2, #32                 @  ip<- r2 - 32
6147    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6148    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6149    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6150    b       .LOP_SHR_LONG_2ADDR_finish
6151
6152/* ------------------------------ */
6153    .balign 64
6154.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6155/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6156    /*
6157     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6158     * 32-bit shift distance.
6159     */
6160    /* ushr-long/2addr vA, vB */
6161    mov     r9, rINST, lsr #8           @ r9<- A+
6162    mov     r3, rINST, lsr #12          @ r3<- B
6163    and     r9, r9, #15
6164    GET_VREG(r2, r3)                    @ r2<- vB
6165    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6166    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6167    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6168
6169    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6170    rsb     r3, r2, #32                 @  r3<- 32 - r2
6171    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6172    subs    ip, r2, #32                 @  ip<- r2 - 32
6173    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6174    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6175    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6176    b       .LOP_USHR_LONG_2ADDR_finish
6177
6178/* ------------------------------ */
6179    .balign 64
6180.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6181/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6182/* File: arm-vfp/fbinop2addr.S */
6183    /*
6184     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6185     * an "instr" line that specifies an instruction that performs
6186     * "s2 = s0 op s1".
6187     *
6188     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6189     */
6190    /* binop/2addr vA, vB */
6191    mov     r3, rINST, lsr #12          @ r3<- B
6192    mov     r9, rINST, lsr #8           @ r9<- A+
6193    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6194    and     r9, r9, #15                 @ r9<- A
6195    flds    s1, [r3]                    @ s1<- vB
6196    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6197    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6198    flds    s0, [r9]                    @ s0<- vA
6199
6200    fadds   s2, s0, s1                              @ s2<- op
6201    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6202    fsts    s2, [r9]                    @ vAA<- s2
6203    GOTO_OPCODE(ip)                     @ jump to next instruction
6204
6205
6206/* ------------------------------ */
6207    .balign 64
6208.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6209/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6210/* File: arm-vfp/fbinop2addr.S */
6211    /*
6212     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6213     * an "instr" line that specifies an instruction that performs
6214     * "s2 = s0 op s1".
6215     *
6216     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6217     */
6218    /* binop/2addr vA, vB */
6219    mov     r3, rINST, lsr #12          @ r3<- B
6220    mov     r9, rINST, lsr #8           @ r9<- A+
6221    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6222    and     r9, r9, #15                 @ r9<- A
6223    flds    s1, [r3]                    @ s1<- vB
6224    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6225    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6226    flds    s0, [r9]                    @ s0<- vA
6227
6228    fsubs   s2, s0, s1                              @ s2<- op
6229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6230    fsts    s2, [r9]                    @ vAA<- s2
6231    GOTO_OPCODE(ip)                     @ jump to next instruction
6232
6233
6234/* ------------------------------ */
6235    .balign 64
6236.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6237/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6238/* File: arm-vfp/fbinop2addr.S */
6239    /*
6240     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6241     * an "instr" line that specifies an instruction that performs
6242     * "s2 = s0 op s1".
6243     *
6244     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6245     */
6246    /* binop/2addr vA, vB */
6247    mov     r3, rINST, lsr #12          @ r3<- B
6248    mov     r9, rINST, lsr #8           @ r9<- A+
6249    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6250    and     r9, r9, #15                 @ r9<- A
6251    flds    s1, [r3]                    @ s1<- vB
6252    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6253    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6254    flds    s0, [r9]                    @ s0<- vA
6255
6256    fmuls   s2, s0, s1                              @ s2<- op
6257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6258    fsts    s2, [r9]                    @ vAA<- s2
6259    GOTO_OPCODE(ip)                     @ jump to next instruction
6260
6261
6262/* ------------------------------ */
6263    .balign 64
6264.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6265/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6266/* File: arm-vfp/fbinop2addr.S */
6267    /*
6268     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6269     * an "instr" line that specifies an instruction that performs
6270     * "s2 = s0 op s1".
6271     *
6272     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6273     */
6274    /* binop/2addr vA, vB */
6275    mov     r3, rINST, lsr #12          @ r3<- B
6276    mov     r9, rINST, lsr #8           @ r9<- A+
6277    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6278    and     r9, r9, #15                 @ r9<- A
6279    flds    s1, [r3]                    @ s1<- vB
6280    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6281    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6282    flds    s0, [r9]                    @ s0<- vA
6283
6284    fdivs   s2, s0, s1                              @ s2<- op
6285    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6286    fsts    s2, [r9]                    @ vAA<- s2
6287    GOTO_OPCODE(ip)                     @ jump to next instruction
6288
6289
6290/* ------------------------------ */
6291    .balign 64
6292.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6293/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6294/* EABI doesn't define a float remainder function, but libm does */
6295/* File: armv5te/binop2addr.S */
6296    /*
6297     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6298     * that specifies an instruction that performs "result = r0 op r1".
6299     * This could be an ARM instruction or a function call.  (If the result
6300     * comes back in a register other than r0, you can override "result".)
6301     *
6302     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6303     * vCC (r1).  Useful for integer division and modulus.
6304     *
6305     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6306     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6307     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6308     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6309     */
6310    /* binop/2addr vA, vB */
6311    mov     r9, rINST, lsr #8           @ r9<- A+
6312    mov     r3, rINST, lsr #12          @ r3<- B
6313    and     r9, r9, #15
6314    GET_VREG(r1, r3)                    @ r1<- vB
6315    GET_VREG(r0, r9)                    @ r0<- vA
6316    .if 0
6317    cmp     r1, #0                      @ is second operand zero?
6318    beq     common_errDivideByZero
6319    .endif
6320    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6321
6322                               @ optional op; may set condition codes
6323    bl      fmodf                              @ r0<- op, r0-r3 changed
6324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6325    SET_VREG(r0, r9)               @ vAA<- r0
6326    GOTO_OPCODE(ip)                     @ jump to next instruction
6327    /* 10-13 instructions */
6328
6329
6330
6331/* ------------------------------ */
6332    .balign 64
6333.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6334/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6335/* File: arm-vfp/fbinopWide2addr.S */
6336    /*
6337     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6338     * an "instr" line that specifies an instruction that performs
6339     * "d2 = d0 op d1".
6340     *
6341     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6342     *      div-double/2addr
6343     */
6344    /* binop/2addr vA, vB */
6345    mov     r3, rINST, lsr #12          @ r3<- B
6346    mov     r9, rINST, lsr #8           @ r9<- A+
6347    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6348    and     r9, r9, #15                 @ r9<- A
6349    fldd    d1, [r3]                    @ d1<- vB
6350    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6351    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6352    fldd    d0, [r9]                    @ d0<- vA
6353
6354    faddd   d2, d0, d1                              @ d2<- op
6355    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6356    fstd    d2, [r9]                    @ vAA<- d2
6357    GOTO_OPCODE(ip)                     @ jump to next instruction
6358
6359
6360/* ------------------------------ */
6361    .balign 64
6362.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6363/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6364/* File: arm-vfp/fbinopWide2addr.S */
6365    /*
6366     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6367     * an "instr" line that specifies an instruction that performs
6368     * "d2 = d0 op d1".
6369     *
6370     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6371     *      div-double/2addr
6372     */
6373    /* binop/2addr vA, vB */
6374    mov     r3, rINST, lsr #12          @ r3<- B
6375    mov     r9, rINST, lsr #8           @ r9<- A+
6376    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6377    and     r9, r9, #15                 @ r9<- A
6378    fldd    d1, [r3]                    @ d1<- vB
6379    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6380    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6381    fldd    d0, [r9]                    @ d0<- vA
6382
6383    fsubd   d2, d0, d1                              @ d2<- op
6384    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6385    fstd    d2, [r9]                    @ vAA<- d2
6386    GOTO_OPCODE(ip)                     @ jump to next instruction
6387
6388
6389/* ------------------------------ */
6390    .balign 64
6391.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6392/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6393/* File: arm-vfp/fbinopWide2addr.S */
6394    /*
6395     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6396     * an "instr" line that specifies an instruction that performs
6397     * "d2 = d0 op d1".
6398     *
6399     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6400     *      div-double/2addr
6401     */
6402    /* binop/2addr vA, vB */
6403    mov     r3, rINST, lsr #12          @ r3<- B
6404    mov     r9, rINST, lsr #8           @ r9<- A+
6405    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6406    and     r9, r9, #15                 @ r9<- A
6407    fldd    d1, [r3]                    @ d1<- vB
6408    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6409    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6410    fldd    d0, [r9]                    @ d0<- vA
6411
6412    fmuld   d2, d0, d1                              @ d2<- op
6413    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6414    fstd    d2, [r9]                    @ vAA<- d2
6415    GOTO_OPCODE(ip)                     @ jump to next instruction
6416
6417
6418/* ------------------------------ */
6419    .balign 64
6420.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6421/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6422/* File: arm-vfp/fbinopWide2addr.S */
6423    /*
6424     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6425     * an "instr" line that specifies an instruction that performs
6426     * "d2 = d0 op d1".
6427     *
6428     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6429     *      div-double/2addr
6430     */
6431    /* binop/2addr vA, vB */
6432    mov     r3, rINST, lsr #12          @ r3<- B
6433    mov     r9, rINST, lsr #8           @ r9<- A+
6434    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6435    and     r9, r9, #15                 @ r9<- A
6436    fldd    d1, [r3]                    @ d1<- vB
6437    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6438    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6439    fldd    d0, [r9]                    @ d0<- vA
6440
6441    fdivd   d2, d0, d1                              @ d2<- op
6442    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6443    fstd    d2, [r9]                    @ vAA<- d2
6444    GOTO_OPCODE(ip)                     @ jump to next instruction
6445
6446
6447/* ------------------------------ */
6448    .balign 64
6449.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6450/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6451/* EABI doesn't define a double remainder function, but libm does */
6452/* File: armv5te/binopWide2addr.S */
6453    /*
6454     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6455     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6456     * This could be an ARM instruction or a function call.  (If the result
6457     * comes back in a register other than r0, you can override "result".)
6458     *
6459     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6460     * vCC (r1).  Useful for integer division and modulus.
6461     *
6462     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6463     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6464     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6465     *      rem-double/2addr
6466     */
6467    /* binop/2addr vA, vB */
6468    mov     r9, rINST, lsr #8           @ r9<- A+
6469    mov     r1, rINST, lsr #12          @ r1<- B
6470    and     r9, r9, #15
6471    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6472    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6473    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6474    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6475    .if 0
6476    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6477    beq     common_errDivideByZero
6478    .endif
6479    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6480
6481                               @ optional op; may set condition codes
6482    bl      fmod                              @ result<- op, r0-r3 changed
6483    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6484    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6485    GOTO_OPCODE(ip)                     @ jump to next instruction
6486    /* 12-15 instructions */
6487
6488
6489
6490/* ------------------------------ */
6491    .balign 64
6492.L_OP_ADD_INT_LIT16: /* 0xd0 */
6493/* File: armv5te/OP_ADD_INT_LIT16.S */
6494/* File: armv5te/binopLit16.S */
6495    /*
6496     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6497     * that specifies an instruction that performs "result = r0 op r1".
6498     * This could be an ARM instruction or a function call.  (If the result
6499     * comes back in a register other than r0, you can override "result".)
6500     *
6501     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6502     * vCC (r1).  Useful for integer division and modulus.
6503     *
6504     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6505     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6506     */
6507    /* binop/lit16 vA, vB, #+CCCC */
6508    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6509    mov     r2, rINST, lsr #12          @ r2<- B
6510    mov     r9, rINST, lsr #8           @ r9<- A+
6511    GET_VREG(r0, r2)                    @ r0<- vB
6512    and     r9, r9, #15
6513    .if 0
6514    cmp     r1, #0                      @ is second operand zero?
6515    beq     common_errDivideByZero
6516    .endif
6517    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6518
6519    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6521    SET_VREG(r0, r9)               @ vAA<- r0
6522    GOTO_OPCODE(ip)                     @ jump to next instruction
6523    /* 10-13 instructions */
6524
6525
6526
6527/* ------------------------------ */
6528    .balign 64
6529.L_OP_RSUB_INT: /* 0xd1 */
6530/* File: armv5te/OP_RSUB_INT.S */
6531/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6532/* File: armv5te/binopLit16.S */
6533    /*
6534     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6535     * that specifies an instruction that performs "result = r0 op r1".
6536     * This could be an ARM instruction or a function call.  (If the result
6537     * comes back in a register other than r0, you can override "result".)
6538     *
6539     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6540     * vCC (r1).  Useful for integer division and modulus.
6541     *
6542     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6543     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6544     */
6545    /* binop/lit16 vA, vB, #+CCCC */
6546    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6547    mov     r2, rINST, lsr #12          @ r2<- B
6548    mov     r9, rINST, lsr #8           @ r9<- A+
6549    GET_VREG(r0, r2)                    @ r0<- vB
6550    and     r9, r9, #15
6551    .if 0
6552    cmp     r1, #0                      @ is second operand zero?
6553    beq     common_errDivideByZero
6554    .endif
6555    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6556
6557    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6559    SET_VREG(r0, r9)               @ vAA<- r0
6560    GOTO_OPCODE(ip)                     @ jump to next instruction
6561    /* 10-13 instructions */
6562
6563
6564
6565/* ------------------------------ */
6566    .balign 64
6567.L_OP_MUL_INT_LIT16: /* 0xd2 */
6568/* File: armv5te/OP_MUL_INT_LIT16.S */
6569/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6570/* File: armv5te/binopLit16.S */
6571    /*
6572     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6573     * that specifies an instruction that performs "result = r0 op r1".
6574     * This could be an ARM instruction or a function call.  (If the result
6575     * comes back in a register other than r0, you can override "result".)
6576     *
6577     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6578     * vCC (r1).  Useful for integer division and modulus.
6579     *
6580     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6581     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6582     */
6583    /* binop/lit16 vA, vB, #+CCCC */
6584    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6585    mov     r2, rINST, lsr #12          @ r2<- B
6586    mov     r9, rINST, lsr #8           @ r9<- A+
6587    GET_VREG(r0, r2)                    @ r0<- vB
6588    and     r9, r9, #15
6589    .if 0
6590    cmp     r1, #0                      @ is second operand zero?
6591    beq     common_errDivideByZero
6592    .endif
6593    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6594
6595    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6596    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6597    SET_VREG(r0, r9)               @ vAA<- r0
6598    GOTO_OPCODE(ip)                     @ jump to next instruction
6599    /* 10-13 instructions */
6600
6601
6602
6603/* ------------------------------ */
6604    .balign 64
6605.L_OP_DIV_INT_LIT16: /* 0xd3 */
6606/* File: armv5te/OP_DIV_INT_LIT16.S */
6607/* File: armv5te/binopLit16.S */
6608    /*
6609     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6610     * that specifies an instruction that performs "result = r0 op r1".
6611     * This could be an ARM instruction or a function call.  (If the result
6612     * comes back in a register other than r0, you can override "result".)
6613     *
6614     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6615     * vCC (r1).  Useful for integer division and modulus.
6616     *
6617     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6618     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6619     */
6620    /* binop/lit16 vA, vB, #+CCCC */
6621    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6622    mov     r2, rINST, lsr #12          @ r2<- B
6623    mov     r9, rINST, lsr #8           @ r9<- A+
6624    GET_VREG(r0, r2)                    @ r0<- vB
6625    and     r9, r9, #15
6626    .if 1
6627    cmp     r1, #0                      @ is second operand zero?
6628    beq     common_errDivideByZero
6629    .endif
6630    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6631
6632    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6633    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6634    SET_VREG(r0, r9)               @ vAA<- r0
6635    GOTO_OPCODE(ip)                     @ jump to next instruction
6636    /* 10-13 instructions */
6637
6638
6639
6640/* ------------------------------ */
6641    .balign 64
6642.L_OP_REM_INT_LIT16: /* 0xd4 */
6643/* File: armv5te/OP_REM_INT_LIT16.S */
6644/* idivmod returns quotient in r0 and remainder in r1 */
6645/* File: armv5te/binopLit16.S */
6646    /*
6647     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6648     * that specifies an instruction that performs "result = r0 op r1".
6649     * This could be an ARM instruction or a function call.  (If the result
6650     * comes back in a register other than r0, you can override "result".)
6651     *
6652     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6653     * vCC (r1).  Useful for integer division and modulus.
6654     *
6655     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6656     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6657     */
6658    /* binop/lit16 vA, vB, #+CCCC */
6659    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6660    mov     r2, rINST, lsr #12          @ r2<- B
6661    mov     r9, rINST, lsr #8           @ r9<- A+
6662    GET_VREG(r0, r2)                    @ r0<- vB
6663    and     r9, r9, #15
6664    .if 1
6665    cmp     r1, #0                      @ is second operand zero?
6666    beq     common_errDivideByZero
6667    .endif
6668    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6669
6670    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6671    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6672    SET_VREG(r1, r9)               @ vAA<- r1
6673    GOTO_OPCODE(ip)                     @ jump to next instruction
6674    /* 10-13 instructions */
6675
6676
6677
6678/* ------------------------------ */
6679    .balign 64
6680.L_OP_AND_INT_LIT16: /* 0xd5 */
6681/* File: armv5te/OP_AND_INT_LIT16.S */
6682/* File: armv5te/binopLit16.S */
6683    /*
6684     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6685     * that specifies an instruction that performs "result = r0 op r1".
6686     * This could be an ARM instruction or a function call.  (If the result
6687     * comes back in a register other than r0, you can override "result".)
6688     *
6689     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6690     * vCC (r1).  Useful for integer division and modulus.
6691     *
6692     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6693     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6694     */
6695    /* binop/lit16 vA, vB, #+CCCC */
6696    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6697    mov     r2, rINST, lsr #12          @ r2<- B
6698    mov     r9, rINST, lsr #8           @ r9<- A+
6699    GET_VREG(r0, r2)                    @ r0<- vB
6700    and     r9, r9, #15
6701    .if 0
6702    cmp     r1, #0                      @ is second operand zero?
6703    beq     common_errDivideByZero
6704    .endif
6705    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6706
6707    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6708    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6709    SET_VREG(r0, r9)               @ vAA<- r0
6710    GOTO_OPCODE(ip)                     @ jump to next instruction
6711    /* 10-13 instructions */
6712
6713
6714
6715/* ------------------------------ */
6716    .balign 64
6717.L_OP_OR_INT_LIT16: /* 0xd6 */
6718/* File: armv5te/OP_OR_INT_LIT16.S */
6719/* File: armv5te/binopLit16.S */
6720    /*
6721     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6722     * that specifies an instruction that performs "result = r0 op r1".
6723     * This could be an ARM instruction or a function call.  (If the result
6724     * comes back in a register other than r0, you can override "result".)
6725     *
6726     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6727     * vCC (r1).  Useful for integer division and modulus.
6728     *
6729     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6730     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6731     */
6732    /* binop/lit16 vA, vB, #+CCCC */
6733    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6734    mov     r2, rINST, lsr #12          @ r2<- B
6735    mov     r9, rINST, lsr #8           @ r9<- A+
6736    GET_VREG(r0, r2)                    @ r0<- vB
6737    and     r9, r9, #15
6738    .if 0
6739    cmp     r1, #0                      @ is second operand zero?
6740    beq     common_errDivideByZero
6741    .endif
6742    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6743
6744    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6746    SET_VREG(r0, r9)               @ vAA<- r0
6747    GOTO_OPCODE(ip)                     @ jump to next instruction
6748    /* 10-13 instructions */
6749
6750
6751
6752/* ------------------------------ */
6753    .balign 64
6754.L_OP_XOR_INT_LIT16: /* 0xd7 */
6755/* File: armv5te/OP_XOR_INT_LIT16.S */
6756/* File: armv5te/binopLit16.S */
6757    /*
6758     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6759     * that specifies an instruction that performs "result = r0 op r1".
6760     * This could be an ARM instruction or a function call.  (If the result
6761     * comes back in a register other than r0, you can override "result".)
6762     *
6763     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6764     * vCC (r1).  Useful for integer division and modulus.
6765     *
6766     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6767     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6768     */
6769    /* binop/lit16 vA, vB, #+CCCC */
6770    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6771    mov     r2, rINST, lsr #12          @ r2<- B
6772    mov     r9, rINST, lsr #8           @ r9<- A+
6773    GET_VREG(r0, r2)                    @ r0<- vB
6774    and     r9, r9, #15
6775    .if 0
6776    cmp     r1, #0                      @ is second operand zero?
6777    beq     common_errDivideByZero
6778    .endif
6779    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6780
6781    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6782    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6783    SET_VREG(r0, r9)               @ vAA<- r0
6784    GOTO_OPCODE(ip)                     @ jump to next instruction
6785    /* 10-13 instructions */
6786
6787
6788
6789/* ------------------------------ */
6790    .balign 64
6791.L_OP_ADD_INT_LIT8: /* 0xd8 */
6792/* File: armv5te/OP_ADD_INT_LIT8.S */
6793/* File: armv5te/binopLit8.S */
6794    /*
6795     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6796     * that specifies an instruction that performs "result = r0 op r1".
6797     * This could be an ARM instruction or a function call.  (If the result
6798     * comes back in a register other than r0, you can override "result".)
6799     *
6800     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6801     * vCC (r1).  Useful for integer division and modulus.
6802     *
6803     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6804     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6805     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6806     */
6807    /* binop/lit8 vAA, vBB, #+CC */
6808    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6809    mov     r9, rINST, lsr #8           @ r9<- AA
6810    and     r2, r3, #255                @ r2<- BB
6811    GET_VREG(r0, r2)                    @ r0<- vBB
6812    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6813    .if 0
6814    @cmp     r1, #0                      @ is second operand zero?
6815    beq     common_errDivideByZero
6816    .endif
6817    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6818
6819                               @ optional op; may set condition codes
6820    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6822    SET_VREG(r0, r9)               @ vAA<- r0
6823    GOTO_OPCODE(ip)                     @ jump to next instruction
6824    /* 10-12 instructions */
6825
6826
6827
6828/* ------------------------------ */
6829    .balign 64
6830.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6831/* File: armv5te/OP_RSUB_INT_LIT8.S */
6832/* File: armv5te/binopLit8.S */
6833    /*
6834     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6835     * that specifies an instruction that performs "result = r0 op r1".
6836     * This could be an ARM instruction or a function call.  (If the result
6837     * comes back in a register other than r0, you can override "result".)
6838     *
6839     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6840     * vCC (r1).  Useful for integer division and modulus.
6841     *
6842     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6843     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6844     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6845     */
6846    /* binop/lit8 vAA, vBB, #+CC */
6847    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6848    mov     r9, rINST, lsr #8           @ r9<- AA
6849    and     r2, r3, #255                @ r2<- BB
6850    GET_VREG(r0, r2)                    @ r0<- vBB
6851    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6852    .if 0
6853    @cmp     r1, #0                      @ is second operand zero?
6854    beq     common_errDivideByZero
6855    .endif
6856    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6857
6858                               @ optional op; may set condition codes
6859    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6861    SET_VREG(r0, r9)               @ vAA<- r0
6862    GOTO_OPCODE(ip)                     @ jump to next instruction
6863    /* 10-12 instructions */
6864
6865
6866
6867/* ------------------------------ */
6868    .balign 64
6869.L_OP_MUL_INT_LIT8: /* 0xda */
6870/* File: armv5te/OP_MUL_INT_LIT8.S */
6871/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6872/* File: armv5te/binopLit8.S */
6873    /*
6874     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6875     * that specifies an instruction that performs "result = r0 op r1".
6876     * This could be an ARM instruction or a function call.  (If the result
6877     * comes back in a register other than r0, you can override "result".)
6878     *
6879     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6880     * vCC (r1).  Useful for integer division and modulus.
6881     *
6882     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6883     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6884     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6885     */
6886    /* binop/lit8 vAA, vBB, #+CC */
6887    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6888    mov     r9, rINST, lsr #8           @ r9<- AA
6889    and     r2, r3, #255                @ r2<- BB
6890    GET_VREG(r0, r2)                    @ r0<- vBB
6891    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6892    .if 0
6893    @cmp     r1, #0                      @ is second operand zero?
6894    beq     common_errDivideByZero
6895    .endif
6896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6897
6898                               @ optional op; may set condition codes
6899    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6901    SET_VREG(r0, r9)               @ vAA<- r0
6902    GOTO_OPCODE(ip)                     @ jump to next instruction
6903    /* 10-12 instructions */
6904
6905
6906
6907/* ------------------------------ */
6908    .balign 64
6909.L_OP_DIV_INT_LIT8: /* 0xdb */
6910/* File: armv5te/OP_DIV_INT_LIT8.S */
6911/* File: armv5te/binopLit8.S */
6912    /*
6913     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6914     * that specifies an instruction that performs "result = r0 op r1".
6915     * This could be an ARM instruction or a function call.  (If the result
6916     * comes back in a register other than r0, you can override "result".)
6917     *
6918     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6919     * vCC (r1).  Useful for integer division and modulus.
6920     *
6921     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6922     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6923     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6924     */
6925    /* binop/lit8 vAA, vBB, #+CC */
6926    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6927    mov     r9, rINST, lsr #8           @ r9<- AA
6928    and     r2, r3, #255                @ r2<- BB
6929    GET_VREG(r0, r2)                    @ r0<- vBB
6930    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6931    .if 1
6932    @cmp     r1, #0                      @ is second operand zero?
6933    beq     common_errDivideByZero
6934    .endif
6935    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6936
6937                               @ optional op; may set condition codes
6938    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6940    SET_VREG(r0, r9)               @ vAA<- r0
6941    GOTO_OPCODE(ip)                     @ jump to next instruction
6942    /* 10-12 instructions */
6943
6944
6945
6946/* ------------------------------ */
6947    .balign 64
6948.L_OP_REM_INT_LIT8: /* 0xdc */
6949/* File: armv5te/OP_REM_INT_LIT8.S */
6950/* idivmod returns quotient in r0 and remainder in r1 */
6951/* File: armv5te/binopLit8.S */
6952    /*
6953     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6954     * that specifies an instruction that performs "result = r0 op r1".
6955     * This could be an ARM instruction or a function call.  (If the result
6956     * comes back in a register other than r0, you can override "result".)
6957     *
6958     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6959     * vCC (r1).  Useful for integer division and modulus.
6960     *
6961     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6962     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6963     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6964     */
6965    /* binop/lit8 vAA, vBB, #+CC */
6966    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6967    mov     r9, rINST, lsr #8           @ r9<- AA
6968    and     r2, r3, #255                @ r2<- BB
6969    GET_VREG(r0, r2)                    @ r0<- vBB
6970    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6971    .if 1
6972    @cmp     r1, #0                      @ is second operand zero?
6973    beq     common_errDivideByZero
6974    .endif
6975    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6976
6977                               @ optional op; may set condition codes
6978    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6980    SET_VREG(r1, r9)               @ vAA<- r1
6981    GOTO_OPCODE(ip)                     @ jump to next instruction
6982    /* 10-12 instructions */
6983
6984
6985
6986/* ------------------------------ */
6987    .balign 64
6988.L_OP_AND_INT_LIT8: /* 0xdd */
6989/* File: armv5te/OP_AND_INT_LIT8.S */
6990/* File: armv5te/binopLit8.S */
6991    /*
6992     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6993     * that specifies an instruction that performs "result = r0 op r1".
6994     * This could be an ARM instruction or a function call.  (If the result
6995     * comes back in a register other than r0, you can override "result".)
6996     *
6997     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6998     * vCC (r1).  Useful for integer division and modulus.
6999     *
7000     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7001     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7002     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7003     */
7004    /* binop/lit8 vAA, vBB, #+CC */
7005    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7006    mov     r9, rINST, lsr #8           @ r9<- AA
7007    and     r2, r3, #255                @ r2<- BB
7008    GET_VREG(r0, r2)                    @ r0<- vBB
7009    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7010    .if 0
7011    @cmp     r1, #0                      @ is second operand zero?
7012    beq     common_errDivideByZero
7013    .endif
7014    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7015
7016                               @ optional op; may set condition codes
7017    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7019    SET_VREG(r0, r9)               @ vAA<- r0
7020    GOTO_OPCODE(ip)                     @ jump to next instruction
7021    /* 10-12 instructions */
7022
7023
7024
7025/* ------------------------------ */
7026    .balign 64
7027.L_OP_OR_INT_LIT8: /* 0xde */
7028/* File: armv5te/OP_OR_INT_LIT8.S */
7029/* File: armv5te/binopLit8.S */
7030    /*
7031     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7032     * that specifies an instruction that performs "result = r0 op r1".
7033     * This could be an ARM instruction or a function call.  (If the result
7034     * comes back in a register other than r0, you can override "result".)
7035     *
7036     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7037     * vCC (r1).  Useful for integer division and modulus.
7038     *
7039     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7040     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7041     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7042     */
7043    /* binop/lit8 vAA, vBB, #+CC */
7044    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7045    mov     r9, rINST, lsr #8           @ r9<- AA
7046    and     r2, r3, #255                @ r2<- BB
7047    GET_VREG(r0, r2)                    @ r0<- vBB
7048    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7049    .if 0
7050    @cmp     r1, #0                      @ is second operand zero?
7051    beq     common_errDivideByZero
7052    .endif
7053    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7054
7055                               @ optional op; may set condition codes
7056    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7057    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7058    SET_VREG(r0, r9)               @ vAA<- r0
7059    GOTO_OPCODE(ip)                     @ jump to next instruction
7060    /* 10-12 instructions */
7061
7062
7063
7064/* ------------------------------ */
7065    .balign 64
7066.L_OP_XOR_INT_LIT8: /* 0xdf */
7067/* File: armv5te/OP_XOR_INT_LIT8.S */
7068/* File: armv5te/binopLit8.S */
7069    /*
7070     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7071     * that specifies an instruction that performs "result = r0 op r1".
7072     * This could be an ARM instruction or a function call.  (If the result
7073     * comes back in a register other than r0, you can override "result".)
7074     *
7075     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7076     * vCC (r1).  Useful for integer division and modulus.
7077     *
7078     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7079     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7080     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7081     */
7082    /* binop/lit8 vAA, vBB, #+CC */
7083    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7084    mov     r9, rINST, lsr #8           @ r9<- AA
7085    and     r2, r3, #255                @ r2<- BB
7086    GET_VREG(r0, r2)                    @ r0<- vBB
7087    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7088    .if 0
7089    @cmp     r1, #0                      @ is second operand zero?
7090    beq     common_errDivideByZero
7091    .endif
7092    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7093
7094                               @ optional op; may set condition codes
7095    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7096    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7097    SET_VREG(r0, r9)               @ vAA<- r0
7098    GOTO_OPCODE(ip)                     @ jump to next instruction
7099    /* 10-12 instructions */
7100
7101
7102
7103/* ------------------------------ */
7104    .balign 64
7105.L_OP_SHL_INT_LIT8: /* 0xe0 */
7106/* File: armv5te/OP_SHL_INT_LIT8.S */
7107/* File: armv5te/binopLit8.S */
7108    /*
7109     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7110     * that specifies an instruction that performs "result = r0 op r1".
7111     * This could be an ARM instruction or a function call.  (If the result
7112     * comes back in a register other than r0, you can override "result".)
7113     *
7114     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7115     * vCC (r1).  Useful for integer division and modulus.
7116     *
7117     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7118     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7119     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7120     */
7121    /* binop/lit8 vAA, vBB, #+CC */
7122    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7123    mov     r9, rINST, lsr #8           @ r9<- AA
7124    and     r2, r3, #255                @ r2<- BB
7125    GET_VREG(r0, r2)                    @ r0<- vBB
7126    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7127    .if 0
7128    @cmp     r1, #0                      @ is second operand zero?
7129    beq     common_errDivideByZero
7130    .endif
7131    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7132
7133    and     r1, r1, #31                           @ optional op; may set condition codes
7134    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7136    SET_VREG(r0, r9)               @ vAA<- r0
7137    GOTO_OPCODE(ip)                     @ jump to next instruction
7138    /* 10-12 instructions */
7139
7140
7141
7142/* ------------------------------ */
7143    .balign 64
7144.L_OP_SHR_INT_LIT8: /* 0xe1 */
7145/* File: armv5te/OP_SHR_INT_LIT8.S */
7146/* File: armv5te/binopLit8.S */
7147    /*
7148     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7149     * that specifies an instruction that performs "result = r0 op r1".
7150     * This could be an ARM instruction or a function call.  (If the result
7151     * comes back in a register other than r0, you can override "result".)
7152     *
7153     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7154     * vCC (r1).  Useful for integer division and modulus.
7155     *
7156     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7157     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7158     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7159     */
7160    /* binop/lit8 vAA, vBB, #+CC */
7161    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7162    mov     r9, rINST, lsr #8           @ r9<- AA
7163    and     r2, r3, #255                @ r2<- BB
7164    GET_VREG(r0, r2)                    @ r0<- vBB
7165    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7166    .if 0
7167    @cmp     r1, #0                      @ is second operand zero?
7168    beq     common_errDivideByZero
7169    .endif
7170    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7171
7172    and     r1, r1, #31                           @ optional op; may set condition codes
7173    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7175    SET_VREG(r0, r9)               @ vAA<- r0
7176    GOTO_OPCODE(ip)                     @ jump to next instruction
7177    /* 10-12 instructions */
7178
7179
7180
7181/* ------------------------------ */
7182    .balign 64
7183.L_OP_USHR_INT_LIT8: /* 0xe2 */
7184/* File: armv5te/OP_USHR_INT_LIT8.S */
7185/* File: armv5te/binopLit8.S */
7186    /*
7187     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7188     * that specifies an instruction that performs "result = r0 op r1".
7189     * This could be an ARM instruction or a function call.  (If the result
7190     * comes back in a register other than r0, you can override "result".)
7191     *
7192     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7193     * vCC (r1).  Useful for integer division and modulus.
7194     *
7195     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7196     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7197     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7198     */
7199    /* binop/lit8 vAA, vBB, #+CC */
7200    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7201    mov     r9, rINST, lsr #8           @ r9<- AA
7202    and     r2, r3, #255                @ r2<- BB
7203    GET_VREG(r0, r2)                    @ r0<- vBB
7204    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7205    .if 0
7206    @cmp     r1, #0                      @ is second operand zero?
7207    beq     common_errDivideByZero
7208    .endif
7209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7210
7211    and     r1, r1, #31                           @ optional op; may set condition codes
7212    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7213    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7214    SET_VREG(r0, r9)               @ vAA<- r0
7215    GOTO_OPCODE(ip)                     @ jump to next instruction
7216    /* 10-12 instructions */
7217
7218
7219
7220/* ------------------------------ */
7221    .balign 64
7222.L_OP_UNUSED_E3: /* 0xe3 */
7223/* File: armv5te/OP_UNUSED_E3.S */
7224/* File: armv5te/unused.S */
7225    bl      common_abort
7226
7227
7228
7229/* ------------------------------ */
7230    .balign 64
7231.L_OP_UNUSED_E4: /* 0xe4 */
7232/* File: armv5te/OP_UNUSED_E4.S */
7233/* File: armv5te/unused.S */
7234    bl      common_abort
7235
7236
7237
7238/* ------------------------------ */
7239    .balign 64
7240.L_OP_UNUSED_E5: /* 0xe5 */
7241/* File: armv5te/OP_UNUSED_E5.S */
7242/* File: armv5te/unused.S */
7243    bl      common_abort
7244
7245
7246
7247/* ------------------------------ */
7248    .balign 64
7249.L_OP_UNUSED_E6: /* 0xe6 */
7250/* File: armv5te/OP_UNUSED_E6.S */
7251/* File: armv5te/unused.S */
7252    bl      common_abort
7253
7254
7255
7256/* ------------------------------ */
7257    .balign 64
7258.L_OP_UNUSED_E7: /* 0xe7 */
7259/* File: armv5te/OP_UNUSED_E7.S */
7260/* File: armv5te/unused.S */
7261    bl      common_abort
7262
7263
7264
7265/* ------------------------------ */
7266    .balign 64
7267.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7268/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7269/* File: armv5te/OP_IGET_WIDE.S */
7270    /*
7271     * Wide 32-bit instance field get.
7272     */
7273    /* iget-wide vA, vB, field@CCCC */
7274    mov     r0, rINST, lsr #12          @ r0<- B
7275    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7276    FETCH(r1, 1)                        @ r1<- field ref CCCC
7277    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7278    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7279    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7280    cmp     r0, #0                      @ is resolved entry null?
7281    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72828:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7283    EXPORT_PC()                         @ resolve() could throw
7284    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7285    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7286    cmp     r0, #0
7287    bne     .LOP_IGET_WIDE_VOLATILE_finish
7288    b       common_exceptionThrown
7289
7290
7291/* ------------------------------ */
7292    .balign 64
7293.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7294/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7295/* File: armv5te/OP_IPUT_WIDE.S */
7296    /* iput-wide vA, vB, field@CCCC */
7297    mov     r0, rINST, lsr #12          @ r0<- B
7298    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7299    FETCH(r1, 1)                        @ r1<- field ref CCCC
7300    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7301    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7302    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7303    cmp     r0, #0                      @ is resolved entry null?
7304    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
73058:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7306    EXPORT_PC()                         @ resolve() could throw
7307    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7308    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7309    cmp     r0, #0                      @ success?
7310    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7311    b       common_exceptionThrown
7312
7313
7314/* ------------------------------ */
7315    .balign 64
7316.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7317/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7318/* File: armv5te/OP_SGET_WIDE.S */
7319    /*
7320     * 64-bit SGET handler.
7321     */
7322    /* sget-wide vAA, field@BBBB */
7323    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7324    FETCH(r1, 1)                        @ r1<- field ref BBBB
7325    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7326    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7327    cmp     r0, #0                      @ is resolved entry null?
7328    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7329.LOP_SGET_WIDE_VOLATILE_finish:
7330    mov     r9, rINST, lsr #8           @ r9<- AA
7331    .if 1
7332    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7333    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
7334    .else
7335    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7336    .endif
7337    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7338    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7339    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7340    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7341    GOTO_OPCODE(ip)                     @ jump to next instruction
7342
7343
7344/* ------------------------------ */
7345    .balign 64
7346.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7347/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7348/* File: armv5te/OP_SPUT_WIDE.S */
7349    /*
7350     * 64-bit SPUT handler.
7351     */
7352    /* sput-wide vAA, field@BBBB */
7353    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7354    FETCH(r1, 1)                        @ r1<- field ref BBBB
7355    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7356    mov     r9, rINST, lsr #8           @ r9<- AA
7357    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7358    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7359    cmp     r2, #0                      @ is resolved entry null?
7360    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7361.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7362    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7363    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7364    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7365    .if 1
7366    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7367    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
7368    .else
7369    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7370    .endif
7371    GOTO_OPCODE(r10)                    @ jump to next instruction
7372
7373
7374/* ------------------------------ */
7375    .balign 64
7376.L_OP_BREAKPOINT: /* 0xec */
7377/* File: armv5te/OP_BREAKPOINT.S */
7378/* File: armv5te/unused.S */
7379    bl      common_abort
7380
7381
7382
7383/* ------------------------------ */
7384    .balign 64
7385.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7386/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7387    /*
7388     * Handle a throw-verification-error instruction.  This throws an
7389     * exception for an error discovered during verification.  The
7390     * exception is indicated by AA, with some detail provided by BBBB.
7391     */
7392    /* op AA, ref@BBBB */
7393    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7394    FETCH(r2, 1)                        @ r2<- BBBB
7395    EXPORT_PC()                         @ export the PC
7396    mov     r1, rINST, lsr #8           @ r1<- AA
7397    bl      dvmThrowVerificationError   @ always throws
7398    b       common_exceptionThrown      @ handle exception
7399
7400
7401/* ------------------------------ */
7402    .balign 64
7403.L_OP_EXECUTE_INLINE: /* 0xee */
7404/* File: armv5te/OP_EXECUTE_INLINE.S */
7405    /*
7406     * Execute a "native inline" instruction.
7407     *
7408     * We need to call an InlineOp4Func:
7409     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7410     *
7411     * The first four args are in r0-r3, pointer to return value storage
7412     * is on the stack.  The function's return value is a flag that tells
7413     * us if an exception was thrown.
7414     */
7415    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7416    FETCH(r10, 1)                       @ r10<- BBBB
7417    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7418    EXPORT_PC()                         @ can throw
7419    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7420    mov     r0, rINST, lsr #12          @ r0<- B
7421    str     r1, [sp]                    @ push &glue->retval
7422    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7423    add     sp, sp, #8                  @ pop stack
7424    cmp     r0, #0                      @ test boolean result of inline
7425    beq     common_exceptionThrown      @ returned false, handle exception
7426    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7428    GOTO_OPCODE(ip)                     @ jump to next instruction
7429
7430/* ------------------------------ */
7431    .balign 64
7432.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7433/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7434    /*
7435     * Execute a "native inline" instruction, using "/range" semantics.
7436     * Same idea as execute-inline, but we get the args differently.
7437     *
7438     * We need to call an InlineOp4Func:
7439     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7440     *
7441     * The first four args are in r0-r3, pointer to return value storage
7442     * is on the stack.  The function's return value is a flag that tells
7443     * us if an exception was thrown.
7444     */
7445    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7446    FETCH(r10, 1)                       @ r10<- BBBB
7447    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7448    EXPORT_PC()                         @ can throw
7449    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7450    mov     r0, rINST, lsr #8           @ r0<- AA
7451    str     r1, [sp]                    @ push &glue->retval
7452    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7453    add     sp, sp, #8                  @ pop stack
7454    cmp     r0, #0                      @ test boolean result of inline
7455    beq     common_exceptionThrown      @ returned false, handle exception
7456    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7458    GOTO_OPCODE(ip)                     @ jump to next instruction
7459
7460/* ------------------------------ */
7461    .balign 64
7462.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7463/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7464    /*
7465     * invoke-direct-empty is a no-op in a "standard" interpreter.
7466     */
7467    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7468    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7469    GOTO_OPCODE(ip)                     @ execute it
7470
7471/* ------------------------------ */
7472    .balign 64
7473.L_OP_UNUSED_F1: /* 0xf1 */
7474/* File: armv5te/OP_UNUSED_F1.S */
7475/* File: armv5te/unused.S */
7476    bl      common_abort
7477
7478
7479
7480/* ------------------------------ */
7481    .balign 64
7482.L_OP_IGET_QUICK: /* 0xf2 */
7483/* File: armv5te/OP_IGET_QUICK.S */
7484    /* For: iget-quick, iget-object-quick */
7485    /* op vA, vB, offset@CCCC */
7486    mov     r2, rINST, lsr #12          @ r2<- B
7487    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7488    FETCH(r1, 1)                        @ r1<- field byte offset
7489    cmp     r3, #0                      @ check object for null
7490    mov     r2, rINST, lsr #8           @ r2<- A(+)
7491    beq     common_errNullObject        @ object was null
7492    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7493    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7494    and     r2, r2, #15
7495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7496    SET_VREG(r0, r2)                    @ fp[A]<- r0
7497    GOTO_OPCODE(ip)                     @ jump to next instruction
7498
7499
7500/* ------------------------------ */
7501    .balign 64
7502.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7503/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7504    /* iget-wide-quick vA, vB, offset@CCCC */
7505    mov     r2, rINST, lsr #12          @ r2<- B
7506    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7507    FETCH(ip, 1)                        @ ip<- field byte offset
7508    cmp     r3, #0                      @ check object for null
7509    mov     r2, rINST, lsr #8           @ r2<- A(+)
7510    beq     common_errNullObject        @ object was null
7511    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7512    and     r2, r2, #15
7513    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7514    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7515    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7516    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7517    GOTO_OPCODE(ip)                     @ jump to next instruction
7518
7519
7520/* ------------------------------ */
7521    .balign 64
7522.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7523/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7524/* File: armv5te/OP_IGET_QUICK.S */
7525    /* For: iget-quick, iget-object-quick */
7526    /* op vA, vB, offset@CCCC */
7527    mov     r2, rINST, lsr #12          @ r2<- B
7528    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7529    FETCH(r1, 1)                        @ r1<- field byte offset
7530    cmp     r3, #0                      @ check object for null
7531    mov     r2, rINST, lsr #8           @ r2<- A(+)
7532    beq     common_errNullObject        @ object was null
7533    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7534    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7535    and     r2, r2, #15
7536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7537    SET_VREG(r0, r2)                    @ fp[A]<- r0
7538    GOTO_OPCODE(ip)                     @ jump to next instruction
7539
7540
7541
7542/* ------------------------------ */
7543    .balign 64
7544.L_OP_IPUT_QUICK: /* 0xf5 */
7545/* File: armv5te/OP_IPUT_QUICK.S */
7546    /* For: iput-quick, iput-object-quick */
7547    /* op vA, vB, offset@CCCC */
7548    mov     r2, rINST, lsr #12          @ r2<- B
7549    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7550    FETCH(r1, 1)                        @ r1<- field byte offset
7551    cmp     r3, #0                      @ check object for null
7552    mov     r2, rINST, lsr #8           @ r2<- A(+)
7553    beq     common_errNullObject        @ object was null
7554    and     r2, r2, #15
7555    GET_VREG(r0, r2)                    @ r0<- fp[A]
7556    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7557    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7559    GOTO_OPCODE(ip)                     @ jump to next instruction
7560
7561
7562/* ------------------------------ */
7563    .balign 64
7564.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7565/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7566    /* iput-wide-quick vA, vB, offset@CCCC */
7567    mov     r0, rINST, lsr #8           @ r0<- A(+)
7568    mov     r1, rINST, lsr #12          @ r1<- B
7569    and     r0, r0, #15
7570    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7571    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7572    cmp     r2, #0                      @ check object for null
7573    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7574    beq     common_errNullObject        @ object was null
7575    FETCH(r3, 1)                        @ r3<- field byte offset
7576    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7577    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7578    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7579    GOTO_OPCODE(ip)                     @ jump to next instruction
7580
7581
7582/* ------------------------------ */
7583    .balign 64
7584.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7585/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7586/* File: armv5te/OP_IPUT_QUICK.S */
7587    /* For: iput-quick, iput-object-quick */
7588    /* op vA, vB, offset@CCCC */
7589    mov     r2, rINST, lsr #12          @ r2<- B
7590    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7591    FETCH(r1, 1)                        @ r1<- field byte offset
7592    cmp     r3, #0                      @ check object for null
7593    mov     r2, rINST, lsr #8           @ r2<- A(+)
7594    beq     common_errNullObject        @ object was null
7595    and     r2, r2, #15
7596    GET_VREG(r0, r2)                    @ r0<- fp[A]
7597    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7598    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7599    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7600    GOTO_OPCODE(ip)                     @ jump to next instruction
7601
7602
7603
7604/* ------------------------------ */
7605    .balign 64
7606.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7607/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7608    /*
7609     * Handle an optimized virtual method call.
7610     *
7611     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7612     */
7613    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7614    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7615    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7616    FETCH(r1, 1)                        @ r1<- BBBB
7617    .if     (!0)
7618    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7619    .endif
7620    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7621    cmp     r2, #0                      @ is "this" null?
7622    beq     common_errNullObject        @ null "this", throw exception
7623    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7624    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7625    EXPORT_PC()                         @ invoke must export
7626    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7627    bl      common_invokeMethodNoRange @ continue on
7628
7629/* ------------------------------ */
7630    .balign 64
7631.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7632/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7633/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7634    /*
7635     * Handle an optimized virtual method call.
7636     *
7637     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7638     */
7639    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7640    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7641    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7642    FETCH(r1, 1)                        @ r1<- BBBB
7643    .if     (!1)
7644    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7645    .endif
7646    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7647    cmp     r2, #0                      @ is "this" null?
7648    beq     common_errNullObject        @ null "this", throw exception
7649    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7650    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7651    EXPORT_PC()                         @ invoke must export
7652    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7653    bl      common_invokeMethodRange @ continue on
7654
7655
7656/* ------------------------------ */
7657    .balign 64
7658.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7659/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7660    /*
7661     * Handle an optimized "super" method call.
7662     *
7663     * for: [opt] invoke-super-quick, invoke-super-quick/range
7664     */
7665    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7666    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7667    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7668    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7669    .if     (!0)
7670    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7671    .endif
7672    FETCH(r1, 1)                        @ r1<- BBBB
7673    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7674    EXPORT_PC()                         @ must export for invoke
7675    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7676    GET_VREG(r3, r10)                   @ r3<- "this"
7677    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7678    cmp     r3, #0                      @ null "this" ref?
7679    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7680    beq     common_errNullObject        @ "this" is null, throw exception
7681    bl      common_invokeMethodNoRange @ continue on
7682
7683
7684/* ------------------------------ */
7685    .balign 64
7686.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7687/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7688/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7689    /*
7690     * Handle an optimized "super" method call.
7691     *
7692     * for: [opt] invoke-super-quick, invoke-super-quick/range
7693     */
7694    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7695    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7696    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7697    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7698    .if     (!1)
7699    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7700    .endif
7701    FETCH(r1, 1)                        @ r1<- BBBB
7702    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7703    EXPORT_PC()                         @ must export for invoke
7704    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7705    GET_VREG(r3, r10)                   @ r3<- "this"
7706    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7707    cmp     r3, #0                      @ null "this" ref?
7708    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7709    beq     common_errNullObject        @ "this" is null, throw exception
7710    bl      common_invokeMethodRange @ continue on
7711
7712
7713
7714/* ------------------------------ */
7715    .balign 64
7716.L_OP_UNUSED_FC: /* 0xfc */
7717/* File: armv5te/OP_UNUSED_FC.S */
7718/* File: armv5te/unused.S */
7719    bl      common_abort
7720
7721
7722
7723/* ------------------------------ */
7724    .balign 64
7725.L_OP_UNUSED_FD: /* 0xfd */
7726/* File: armv5te/OP_UNUSED_FD.S */
7727/* File: armv5te/unused.S */
7728    bl      common_abort
7729
7730
7731
7732/* ------------------------------ */
7733    .balign 64
7734.L_OP_UNUSED_FE: /* 0xfe */
7735/* File: armv5te/OP_UNUSED_FE.S */
7736/* File: armv5te/unused.S */
7737    bl      common_abort
7738
7739
7740
7741/* ------------------------------ */
7742    .balign 64
7743.L_OP_UNUSED_FF: /* 0xff */
7744/* File: armv5te/OP_UNUSED_FF.S */
7745/* File: armv5te/unused.S */
7746    bl      common_abort
7747
7748
7749
7750
7751    .balign 64
7752    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7753    .global dvmAsmInstructionEnd
7754dvmAsmInstructionEnd:
7755
7756/*
7757 * ===========================================================================
7758 *  Sister implementations
7759 * ===========================================================================
7760 */
7761    .global dvmAsmSisterStart
7762    .type   dvmAsmSisterStart, %function
7763    .text
7764    .balign 4
7765dvmAsmSisterStart:
7766
7767/* continuation for OP_CONST_STRING */
7768
7769    /*
7770     * Continuation if the String has not yet been resolved.
7771     *  r1: BBBB (String ref)
7772     *  r9: target register
7773     */
7774.LOP_CONST_STRING_resolve:
7775    EXPORT_PC()
7776    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7777    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7778    bl      dvmResolveString            @ r0<- String reference
7779    cmp     r0, #0                      @ failed?
7780    beq     common_exceptionThrown      @ yup, handle the exception
7781    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7782    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7783    SET_VREG(r0, r9)                    @ vAA<- r0
7784    GOTO_OPCODE(ip)                     @ jump to next instruction
7785
7786
7787/* continuation for OP_CONST_STRING_JUMBO */
7788
7789    /*
7790     * Continuation if the String has not yet been resolved.
7791     *  r1: BBBBBBBB (String ref)
7792     *  r9: target register
7793     */
7794.LOP_CONST_STRING_JUMBO_resolve:
7795    EXPORT_PC()
7796    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7797    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7798    bl      dvmResolveString            @ r0<- String reference
7799    cmp     r0, #0                      @ failed?
7800    beq     common_exceptionThrown      @ yup, handle the exception
7801    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7803    SET_VREG(r0, r9)                    @ vAA<- r0
7804    GOTO_OPCODE(ip)                     @ jump to next instruction
7805
7806
7807/* continuation for OP_CONST_CLASS */
7808
7809    /*
7810     * Continuation if the Class has not yet been resolved.
7811     *  r1: BBBB (Class ref)
7812     *  r9: target register
7813     */
7814.LOP_CONST_CLASS_resolve:
7815    EXPORT_PC()
7816    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7817    mov     r2, #1                      @ r2<- true
7818    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7819    bl      dvmResolveClass             @ r0<- Class reference
7820    cmp     r0, #0                      @ failed?
7821    beq     common_exceptionThrown      @ yup, handle the exception
7822    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7823    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7824    SET_VREG(r0, r9)                    @ vAA<- r0
7825    GOTO_OPCODE(ip)                     @ jump to next instruction
7826
7827
7828/* continuation for OP_CHECK_CAST */
7829
7830    /*
7831     * Trivial test failed, need to perform full check.  This is common.
7832     *  r0 holds obj->clazz
7833     *  r1 holds class resolved from BBBB
7834     *  r9 holds object
7835     */
7836.LOP_CHECK_CAST_fullcheck:
7837    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7838    cmp     r0, #0                      @ failed?
7839    bne     .LOP_CHECK_CAST_okay            @ no, success
7840
7841    @ A cast has failed.  We need to throw a ClassCastException with the
7842    @ class of the object that failed to be cast.
7843    EXPORT_PC()                         @ about to throw
7844    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7845    ldr     r0, .LstrClassCastExceptionPtr
7846    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7847    bl      dvmThrowExceptionWithClassMessage
7848    b       common_exceptionThrown
7849
7850    /*
7851     * Resolution required.  This is the least-likely path.
7852     *
7853     *  r2 holds BBBB
7854     *  r9 holds object
7855     */
7856.LOP_CHECK_CAST_resolve:
7857    EXPORT_PC()                         @ resolve() could throw
7858    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7859    mov     r1, r2                      @ r1<- BBBB
7860    mov     r2, #0                      @ r2<- false
7861    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7862    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7863    cmp     r0, #0                      @ got null?
7864    beq     common_exceptionThrown      @ yes, handle exception
7865    mov     r1, r0                      @ r1<- class resolved from BBB
7866    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7867    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7868
7869.LstrClassCastExceptionPtr:
7870    .word   .LstrClassCastException
7871
7872
7873/* continuation for OP_INSTANCE_OF */
7874
7875    /*
7876     * Trivial test failed, need to perform full check.  This is common.
7877     *  r0 holds obj->clazz
7878     *  r1 holds class resolved from BBBB
7879     *  r9 holds A
7880     */
7881.LOP_INSTANCE_OF_fullcheck:
7882    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7883    @ fall through to OP_INSTANCE_OF_store
7884
7885    /*
7886     * r0 holds boolean result
7887     * r9 holds A
7888     */
7889.LOP_INSTANCE_OF_store:
7890    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7891    SET_VREG(r0, r9)                    @ vA<- r0
7892    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7893    GOTO_OPCODE(ip)                     @ jump to next instruction
7894
7895    /*
7896     * Trivial test succeeded, save and bail.
7897     *  r9 holds A
7898     */
7899.LOP_INSTANCE_OF_trivial:
7900    mov     r0, #1                      @ indicate success
7901    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7902    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7903    SET_VREG(r0, r9)                    @ vA<- r0
7904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7905    GOTO_OPCODE(ip)                     @ jump to next instruction
7906
7907    /*
7908     * Resolution required.  This is the least-likely path.
7909     *
7910     *  r3 holds BBBB
7911     *  r9 holds A
7912     */
7913.LOP_INSTANCE_OF_resolve:
7914    EXPORT_PC()                         @ resolve() could throw
7915    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7916    mov     r1, r3                      @ r1<- BBBB
7917    mov     r2, #1                      @ r2<- true
7918    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7919    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7920    cmp     r0, #0                      @ got null?
7921    beq     common_exceptionThrown      @ yes, handle exception
7922    mov     r1, r0                      @ r1<- class resolved from BBB
7923    mov     r3, rINST, lsr #12          @ r3<- B
7924    GET_VREG(r0, r3)                    @ r0<- vB (object)
7925    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7926    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7927
7928
7929/* continuation for OP_NEW_INSTANCE */
7930
7931    .balign 32                          @ minimize cache lines
7932.LOP_NEW_INSTANCE_finish: @ r0=new object
7933    mov     r3, rINST, lsr #8           @ r3<- AA
7934    cmp     r0, #0                      @ failed?
7935    beq     common_exceptionThrown      @ yes, handle the exception
7936    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7938    SET_VREG(r0, r3)                    @ vAA<- r0
7939    GOTO_OPCODE(ip)                     @ jump to next instruction
7940
7941    /*
7942     * Class initialization required.
7943     *
7944     *  r0 holds class object
7945     */
7946.LOP_NEW_INSTANCE_needinit:
7947    mov     r9, r0                      @ save r0
7948    bl      dvmInitClass                @ initialize class
7949    cmp     r0, #0                      @ check boolean result
7950    mov     r0, r9                      @ restore r0
7951    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7952    b       common_exceptionThrown      @ failed, deal with init exception
7953
7954    /*
7955     * Resolution required.  This is the least-likely path.
7956     *
7957     *  r1 holds BBBB
7958     */
7959.LOP_NEW_INSTANCE_resolve:
7960    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7961    mov     r2, #0                      @ r2<- false
7962    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7963    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7964    cmp     r0, #0                      @ got null?
7965    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7966    b       common_exceptionThrown      @ yes, handle exception
7967
7968.LstrInstantiationErrorPtr:
7969    .word   .LstrInstantiationError
7970
7971
7972/* continuation for OP_NEW_ARRAY */
7973
7974
7975    /*
7976     * Resolve class.  (This is an uncommon case.)
7977     *
7978     *  r1 holds array length
7979     *  r2 holds class ref CCCC
7980     */
7981.LOP_NEW_ARRAY_resolve:
7982    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7983    mov     r9, r1                      @ r9<- length (save)
7984    mov     r1, r2                      @ r1<- CCCC
7985    mov     r2, #0                      @ r2<- false
7986    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7987    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7988    cmp     r0, #0                      @ got null?
7989    mov     r1, r9                      @ r1<- length (restore)
7990    beq     common_exceptionThrown      @ yes, handle exception
7991    @ fall through to OP_NEW_ARRAY_finish
7992
7993    /*
7994     * Finish allocation.
7995     *
7996     *  r0 holds class
7997     *  r1 holds array length
7998     */
7999.LOP_NEW_ARRAY_finish:
8000    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8001    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8002    cmp     r0, #0                      @ failed?
8003    mov     r2, rINST, lsr #8           @ r2<- A+
8004    beq     common_exceptionThrown      @ yes, handle the exception
8005    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8006    and     r2, r2, #15                 @ r2<- A
8007    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8008    SET_VREG(r0, r2)                    @ vA<- r0
8009    GOTO_OPCODE(ip)                     @ jump to next instruction
8010
8011
8012/* continuation for OP_FILLED_NEW_ARRAY */
8013
8014    /*
8015     * On entry:
8016     *  r0 holds array class
8017     *  r10 holds AA or BA
8018     */
8019.LOP_FILLED_NEW_ARRAY_continue:
8020    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8021    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8022    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8023    .if     0
8024    mov     r1, r10                     @ r1<- AA (length)
8025    .else
8026    mov     r1, r10, lsr #4             @ r1<- B (length)
8027    .endif
8028    cmp     r3, #'I'                    @ array of ints?
8029    cmpne   r3, #'L'                    @ array of objects?
8030    cmpne   r3, #'['                    @ array of arrays?
8031    mov     r9, r1                      @ save length in r9
8032    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8033    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8034    cmp     r0, #0                      @ null return?
8035    beq     common_exceptionThrown      @ alloc failed, handle exception
8036
8037    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8038    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8039    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8040    subs    r9, r9, #1                  @ length--, check for neg
8041    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8042    bmi     2f                          @ was zero, bail
8043
8044    @ copy values from registers into the array
8045    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8046    .if     0
8047    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80481:  ldr     r3, [r2], #4                @ r3<- *r2++
8049    subs    r9, r9, #1                  @ count--
8050    str     r3, [r0], #4                @ *contents++ = vX
8051    bpl     1b
8052    @ continue at 2
8053    .else
8054    cmp     r9, #4                      @ length was initially 5?
8055    and     r2, r10, #15                @ r2<- A
8056    bne     1f                          @ <= 4 args, branch
8057    GET_VREG(r3, r2)                    @ r3<- vA
8058    sub     r9, r9, #1                  @ count--
8059    str     r3, [r0, #16]               @ contents[4] = vA
80601:  and     r2, r1, #15                 @ r2<- F/E/D/C
8061    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8062    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8063    subs    r9, r9, #1                  @ count--
8064    str     r3, [r0], #4                @ *contents++ = vX
8065    bpl     1b
8066    @ continue at 2
8067    .endif
8068
80692:
8070    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8071    GOTO_OPCODE(ip)                     @ execute it
8072
8073    /*
8074     * Throw an exception indicating that we have not implemented this
8075     * mode of filled-new-array.
8076     */
8077.LOP_FILLED_NEW_ARRAY_notimpl:
8078    ldr     r0, .L_strInternalError
8079    ldr     r1, .L_strFilledNewArrayNotImpl
8080    bl      dvmThrowException
8081    b       common_exceptionThrown
8082
8083    .if     (!0)                 @ define in one or the other, not both
8084.L_strFilledNewArrayNotImpl:
8085    .word   .LstrFilledNewArrayNotImpl
8086.L_strInternalError:
8087    .word   .LstrInternalError
8088    .endif
8089
8090
8091/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8092
8093    /*
8094     * On entry:
8095     *  r0 holds array class
8096     *  r10 holds AA or BA
8097     */
8098.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8099    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8100    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8101    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8102    .if     1
8103    mov     r1, r10                     @ r1<- AA (length)
8104    .else
8105    mov     r1, r10, lsr #4             @ r1<- B (length)
8106    .endif
8107    cmp     r3, #'I'                    @ array of ints?
8108    cmpne   r3, #'L'                    @ array of objects?
8109    cmpne   r3, #'['                    @ array of arrays?
8110    mov     r9, r1                      @ save length in r9
8111    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8112    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8113    cmp     r0, #0                      @ null return?
8114    beq     common_exceptionThrown      @ alloc failed, handle exception
8115
8116    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8117    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8118    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8119    subs    r9, r9, #1                  @ length--, check for neg
8120    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8121    bmi     2f                          @ was zero, bail
8122
8123    @ copy values from registers into the array
8124    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8125    .if     1
8126    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81271:  ldr     r3, [r2], #4                @ r3<- *r2++
8128    subs    r9, r9, #1                  @ count--
8129    str     r3, [r0], #4                @ *contents++ = vX
8130    bpl     1b
8131    @ continue at 2
8132    .else
8133    cmp     r9, #4                      @ length was initially 5?
8134    and     r2, r10, #15                @ r2<- A
8135    bne     1f                          @ <= 4 args, branch
8136    GET_VREG(r3, r2)                    @ r3<- vA
8137    sub     r9, r9, #1                  @ count--
8138    str     r3, [r0, #16]               @ contents[4] = vA
81391:  and     r2, r1, #15                 @ r2<- F/E/D/C
8140    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8141    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8142    subs    r9, r9, #1                  @ count--
8143    str     r3, [r0], #4                @ *contents++ = vX
8144    bpl     1b
8145    @ continue at 2
8146    .endif
8147
81482:
8149    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8150    GOTO_OPCODE(ip)                     @ execute it
8151
8152    /*
8153     * Throw an exception indicating that we have not implemented this
8154     * mode of filled-new-array.
8155     */
8156.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8157    ldr     r0, .L_strInternalError
8158    ldr     r1, .L_strFilledNewArrayNotImpl
8159    bl      dvmThrowException
8160    b       common_exceptionThrown
8161
8162    .if     (!1)                 @ define in one or the other, not both
8163.L_strFilledNewArrayNotImpl:
8164    .word   .LstrFilledNewArrayNotImpl
8165.L_strInternalError:
8166    .word   .LstrInternalError
8167    .endif
8168
8169
8170/* continuation for OP_CMPL_FLOAT */
8171.LOP_CMPL_FLOAT_finish:
8172    SET_VREG(r0, r9)                    @ vAA<- r0
8173    GOTO_OPCODE(ip)                     @ jump to next instruction
8174
8175
8176/* continuation for OP_CMPG_FLOAT */
8177.LOP_CMPG_FLOAT_finish:
8178    SET_VREG(r0, r9)                    @ vAA<- r0
8179    GOTO_OPCODE(ip)                     @ jump to next instruction
8180
8181
8182/* continuation for OP_CMPL_DOUBLE */
8183.LOP_CMPL_DOUBLE_finish:
8184    SET_VREG(r0, r9)                    @ vAA<- r0
8185    GOTO_OPCODE(ip)                     @ jump to next instruction
8186
8187
8188/* continuation for OP_CMPG_DOUBLE */
8189.LOP_CMPG_DOUBLE_finish:
8190    SET_VREG(r0, r9)                    @ vAA<- r0
8191    GOTO_OPCODE(ip)                     @ jump to next instruction
8192
8193
8194/* continuation for OP_CMP_LONG */
8195
8196.LOP_CMP_LONG_less:
8197    mvn     r1, #0                      @ r1<- -1
8198    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8199    @ instead, we just replicate the tail end.
8200    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8201    SET_VREG(r1, r9)                    @ vAA<- r1
8202    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8203    GOTO_OPCODE(ip)                     @ jump to next instruction
8204
8205.LOP_CMP_LONG_greater:
8206    mov     r1, #1                      @ r1<- 1
8207    @ fall through to _finish
8208
8209.LOP_CMP_LONG_finish:
8210    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8211    SET_VREG(r1, r9)                    @ vAA<- r1
8212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8213    GOTO_OPCODE(ip)                     @ jump to next instruction
8214
8215
8216/* continuation for OP_AGET_WIDE */
8217
8218.LOP_AGET_WIDE_finish:
8219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8220    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8221    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8223    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8224    GOTO_OPCODE(ip)                     @ jump to next instruction
8225
8226
8227/* continuation for OP_APUT_WIDE */
8228
8229.LOP_APUT_WIDE_finish:
8230    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8231    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8232    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8233    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8234    GOTO_OPCODE(ip)                     @ jump to next instruction
8235
8236
8237/* continuation for OP_APUT_OBJECT */
8238    /*
8239     * On entry:
8240     *  r1 = vBB (arrayObj)
8241     *  r9 = vAA (obj)
8242     *  r10 = offset into array (vBB + vCC * width)
8243     */
8244.LOP_APUT_OBJECT_finish:
8245    cmp     r9, #0                      @ storing null reference?
8246    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8247    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8248    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8249    bl      dvmCanPutArrayElement       @ test object type vs. array type
8250    cmp     r0, #0                      @ okay?
8251    beq     common_errArrayStore        @ no
8252.LOP_APUT_OBJECT_skip_check:
8253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8254    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8255    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8256    GOTO_OPCODE(ip)                     @ jump to next instruction
8257
8258
8259/* continuation for OP_IGET */
8260
8261    /*
8262     * Currently:
8263     *  r0 holds resolved field
8264     *  r9 holds object
8265     */
8266.LOP_IGET_finish:
8267    @bl      common_squeak0
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_WIDE */
8281
8282    /*
8283     * Currently:
8284     *  r0 holds resolved field
8285     *  r9 holds object
8286     */
8287.LOP_IGET_WIDE_finish:
8288    cmp     r9, #0                      @ check object for null
8289    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8290    beq     common_errNullObject        @ object was null
8291    .if 0
8292    add     r0, r9, r3                  @ r0<- address of field
8293    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
8294    .else
8295    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8296    .endif
8297    mov     r2, rINST, lsr #8           @ r2<- A+
8298    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8299    and     r2, r2, #15                 @ r2<- A
8300    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8301    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8302    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8303    GOTO_OPCODE(ip)                     @ jump to next instruction
8304
8305
8306/* continuation for OP_IGET_OBJECT */
8307
8308    /*
8309     * Currently:
8310     *  r0 holds resolved field
8311     *  r9 holds object
8312     */
8313.LOP_IGET_OBJECT_finish:
8314    @bl      common_squeak0
8315    cmp     r9, #0                      @ check object for null
8316    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8317    beq     common_errNullObject        @ object was null
8318    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8319    mov     r2, rINST, lsr #8           @ r2<- A+
8320    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8321    and     r2, r2, #15                 @ r2<- A
8322    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8323    SET_VREG(r0, r2)                    @ fp[A]<- r0
8324    GOTO_OPCODE(ip)                     @ jump to next instruction
8325
8326
8327/* continuation for OP_IGET_BOOLEAN */
8328
8329    /*
8330     * Currently:
8331     *  r0 holds resolved field
8332     *  r9 holds object
8333     */
8334.LOP_IGET_BOOLEAN_finish:
8335    @bl      common_squeak1
8336    cmp     r9, #0                      @ check object for null
8337    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8338    beq     common_errNullObject        @ object was null
8339    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8340    mov     r2, rINST, lsr #8           @ r2<- A+
8341    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8342    and     r2, r2, #15                 @ r2<- A
8343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8344    SET_VREG(r0, r2)                    @ fp[A]<- r0
8345    GOTO_OPCODE(ip)                     @ jump to next instruction
8346
8347
8348/* continuation for OP_IGET_BYTE */
8349
8350    /*
8351     * Currently:
8352     *  r0 holds resolved field
8353     *  r9 holds object
8354     */
8355.LOP_IGET_BYTE_finish:
8356    @bl      common_squeak2
8357    cmp     r9, #0                      @ check object for null
8358    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8359    beq     common_errNullObject        @ object was null
8360    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8361    mov     r2, rINST, lsr #8           @ r2<- A+
8362    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8363    and     r2, r2, #15                 @ r2<- A
8364    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8365    SET_VREG(r0, r2)                    @ fp[A]<- r0
8366    GOTO_OPCODE(ip)                     @ jump to next instruction
8367
8368
8369/* continuation for OP_IGET_CHAR */
8370
8371    /*
8372     * Currently:
8373     *  r0 holds resolved field
8374     *  r9 holds object
8375     */
8376.LOP_IGET_CHAR_finish:
8377    @bl      common_squeak3
8378    cmp     r9, #0                      @ check object for null
8379    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8380    beq     common_errNullObject        @ object was null
8381    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8382    mov     r2, rINST, lsr #8           @ r2<- A+
8383    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8384    and     r2, r2, #15                 @ r2<- A
8385    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8386    SET_VREG(r0, r2)                    @ fp[A]<- r0
8387    GOTO_OPCODE(ip)                     @ jump to next instruction
8388
8389
8390/* continuation for OP_IGET_SHORT */
8391
8392    /*
8393     * Currently:
8394     *  r0 holds resolved field
8395     *  r9 holds object
8396     */
8397.LOP_IGET_SHORT_finish:
8398    @bl      common_squeak4
8399    cmp     r9, #0                      @ check object for null
8400    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8401    beq     common_errNullObject        @ object was null
8402    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8403    mov     r2, rINST, lsr #8           @ r2<- A+
8404    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8405    and     r2, r2, #15                 @ r2<- A
8406    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8407    SET_VREG(r0, r2)                    @ fp[A]<- r0
8408    GOTO_OPCODE(ip)                     @ jump to next instruction
8409
8410
8411/* continuation for OP_IPUT */
8412
8413    /*
8414     * Currently:
8415     *  r0 holds resolved field
8416     *  r9 holds object
8417     */
8418.LOP_IPUT_finish:
8419    @bl      common_squeak0
8420    mov     r1, rINST, lsr #8           @ r1<- A+
8421    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8422    and     r1, r1, #15                 @ r1<- A
8423    cmp     r9, #0                      @ check object for null
8424    GET_VREG(r0, r1)                    @ r0<- fp[A]
8425    beq     common_errNullObject        @ object was null
8426    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8427    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8428    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8429    GOTO_OPCODE(ip)                     @ jump to next instruction
8430
8431
8432/* continuation for OP_IPUT_WIDE */
8433
8434    /*
8435     * Currently:
8436     *  r0 holds resolved field
8437     *  r9 holds object
8438     */
8439.LOP_IPUT_WIDE_finish:
8440    mov     r2, rINST, lsr #8           @ r2<- A+
8441    cmp     r9, #0                      @ check object for null
8442    and     r2, r2, #15                 @ r2<- A
8443    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8444    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8445    beq     common_errNullObject        @ object was null
8446    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8447    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8448    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8449    .if 0
8450    add     r2, r9, r3                  @ r2<- target address
8451    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
8452    .else
8453    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8454    .endif
8455    GOTO_OPCODE(r10)                    @ jump to next instruction
8456
8457
8458/* continuation for OP_IPUT_OBJECT */
8459
8460    /*
8461     * Currently:
8462     *  r0 holds resolved field
8463     *  r9 holds object
8464     */
8465.LOP_IPUT_OBJECT_finish:
8466    @bl      common_squeak0
8467    mov     r1, rINST, lsr #8           @ r1<- A+
8468    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8469    and     r1, r1, #15                 @ r1<- A
8470    cmp     r9, #0                      @ check object for null
8471    GET_VREG(r0, r1)                    @ r0<- fp[A]
8472    beq     common_errNullObject        @ object was null
8473    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8475    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8476    GOTO_OPCODE(ip)                     @ jump to next instruction
8477
8478
8479/* continuation for OP_IPUT_BOOLEAN */
8480
8481    /*
8482     * Currently:
8483     *  r0 holds resolved field
8484     *  r9 holds object
8485     */
8486.LOP_IPUT_BOOLEAN_finish:
8487    @bl      common_squeak1
8488    mov     r1, rINST, lsr #8           @ r1<- A+
8489    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8490    and     r1, r1, #15                 @ r1<- A
8491    cmp     r9, #0                      @ check object for null
8492    GET_VREG(r0, r1)                    @ r0<- fp[A]
8493    beq     common_errNullObject        @ object was null
8494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8496    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8497    GOTO_OPCODE(ip)                     @ jump to next instruction
8498
8499
8500/* continuation for OP_IPUT_BYTE */
8501
8502    /*
8503     * Currently:
8504     *  r0 holds resolved field
8505     *  r9 holds object
8506     */
8507.LOP_IPUT_BYTE_finish:
8508    @bl      common_squeak2
8509    mov     r1, rINST, lsr #8           @ r1<- A+
8510    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8511    and     r1, r1, #15                 @ r1<- A
8512    cmp     r9, #0                      @ check object for null
8513    GET_VREG(r0, r1)                    @ r0<- fp[A]
8514    beq     common_errNullObject        @ object was null
8515    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8517    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8518    GOTO_OPCODE(ip)                     @ jump to next instruction
8519
8520
8521/* continuation for OP_IPUT_CHAR */
8522
8523    /*
8524     * Currently:
8525     *  r0 holds resolved field
8526     *  r9 holds object
8527     */
8528.LOP_IPUT_CHAR_finish:
8529    @bl      common_squeak3
8530    mov     r1, rINST, lsr #8           @ r1<- A+
8531    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8532    and     r1, r1, #15                 @ r1<- A
8533    cmp     r9, #0                      @ check object for null
8534    GET_VREG(r0, r1)                    @ r0<- fp[A]
8535    beq     common_errNullObject        @ object was null
8536    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8538    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8539    GOTO_OPCODE(ip)                     @ jump to next instruction
8540
8541
8542/* continuation for OP_IPUT_SHORT */
8543
8544    /*
8545     * Currently:
8546     *  r0 holds resolved field
8547     *  r9 holds object
8548     */
8549.LOP_IPUT_SHORT_finish:
8550    @bl      common_squeak4
8551    mov     r1, rINST, lsr #8           @ r1<- A+
8552    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8553    and     r1, r1, #15                 @ r1<- A
8554    cmp     r9, #0                      @ check object for null
8555    GET_VREG(r0, r1)                    @ r0<- fp[A]
8556    beq     common_errNullObject        @ object was null
8557    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8559    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8560    GOTO_OPCODE(ip)                     @ jump to next instruction
8561
8562
8563/* continuation for OP_SGET */
8564
8565    /*
8566     * Continuation if the field has not yet been resolved.
8567     *  r1: BBBB field ref
8568     */
8569.LOP_SGET_resolve:
8570    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8571    EXPORT_PC()                         @ resolve() could throw, so export now
8572    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8573    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8574    cmp     r0, #0                      @ success?
8575    bne     .LOP_SGET_finish          @ yes, finish
8576    b       common_exceptionThrown      @ no, handle exception
8577
8578
8579/* continuation for OP_SGET_WIDE */
8580
8581    /*
8582     * Continuation if the field has not yet been resolved.
8583     *  r1: BBBB field ref
8584     *
8585     * Returns StaticField pointer in r0.
8586     */
8587.LOP_SGET_WIDE_resolve:
8588    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8589    EXPORT_PC()                         @ resolve() could throw, so export now
8590    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8591    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8592    cmp     r0, #0                      @ success?
8593    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8594    b       common_exceptionThrown      @ no, handle exception
8595
8596
8597/* continuation for OP_SGET_OBJECT */
8598
8599    /*
8600     * Continuation if the field has not yet been resolved.
8601     *  r1: BBBB field ref
8602     */
8603.LOP_SGET_OBJECT_resolve:
8604    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8605    EXPORT_PC()                         @ resolve() could throw, so export now
8606    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8607    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8608    cmp     r0, #0                      @ success?
8609    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8610    b       common_exceptionThrown      @ no, handle exception
8611
8612
8613/* continuation for OP_SGET_BOOLEAN */
8614
8615    /*
8616     * Continuation if the field has not yet been resolved.
8617     *  r1: BBBB field ref
8618     */
8619.LOP_SGET_BOOLEAN_resolve:
8620    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8621    EXPORT_PC()                         @ resolve() could throw, so export now
8622    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8623    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8624    cmp     r0, #0                      @ success?
8625    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8626    b       common_exceptionThrown      @ no, handle exception
8627
8628
8629/* continuation for OP_SGET_BYTE */
8630
8631    /*
8632     * Continuation if the field has not yet been resolved.
8633     *  r1: BBBB field ref
8634     */
8635.LOP_SGET_BYTE_resolve:
8636    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8637    EXPORT_PC()                         @ resolve() could throw, so export now
8638    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8639    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8640    cmp     r0, #0                      @ success?
8641    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8642    b       common_exceptionThrown      @ no, handle exception
8643
8644
8645/* continuation for OP_SGET_CHAR */
8646
8647    /*
8648     * Continuation if the field has not yet been resolved.
8649     *  r1: BBBB field ref
8650     */
8651.LOP_SGET_CHAR_resolve:
8652    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8653    EXPORT_PC()                         @ resolve() could throw, so export now
8654    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8655    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8656    cmp     r0, #0                      @ success?
8657    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8658    b       common_exceptionThrown      @ no, handle exception
8659
8660
8661/* continuation for OP_SGET_SHORT */
8662
8663    /*
8664     * Continuation if the field has not yet been resolved.
8665     *  r1: BBBB field ref
8666     */
8667.LOP_SGET_SHORT_resolve:
8668    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8669    EXPORT_PC()                         @ resolve() could throw, so export now
8670    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8671    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8672    cmp     r0, #0                      @ success?
8673    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8674    b       common_exceptionThrown      @ no, handle exception
8675
8676
8677/* continuation for OP_SPUT */
8678
8679    /*
8680     * Continuation if the field has not yet been resolved.
8681     *  r1: BBBB field ref
8682     */
8683.LOP_SPUT_resolve:
8684    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8685    EXPORT_PC()                         @ resolve() could throw, so export now
8686    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8687    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8688    cmp     r0, #0                      @ success?
8689    bne     .LOP_SPUT_finish          @ yes, finish
8690    b       common_exceptionThrown      @ no, handle exception
8691
8692
8693/* continuation for OP_SPUT_WIDE */
8694
8695    /*
8696     * Continuation if the field has not yet been resolved.
8697     *  r1: BBBB field ref
8698     *  r9: &fp[AA]
8699     *
8700     * Returns StaticField pointer in r2.
8701     */
8702.LOP_SPUT_WIDE_resolve:
8703    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8704    EXPORT_PC()                         @ resolve() could throw, so export now
8705    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8706    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8707    cmp     r0, #0                      @ success?
8708    mov     r2, r0                      @ copy to r2
8709    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8710    b       common_exceptionThrown      @ no, handle exception
8711
8712
8713/* continuation for OP_SPUT_OBJECT */
8714
8715    /*
8716     * Continuation if the field has not yet been resolved.
8717     *  r1: BBBB field ref
8718     */
8719.LOP_SPUT_OBJECT_resolve:
8720    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8721    EXPORT_PC()                         @ resolve() could throw, so export now
8722    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8723    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8724    cmp     r0, #0                      @ success?
8725    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8726    b       common_exceptionThrown      @ no, handle exception
8727
8728
8729/* continuation for OP_SPUT_BOOLEAN */
8730
8731    /*
8732     * Continuation if the field has not yet been resolved.
8733     *  r1: BBBB field ref
8734     */
8735.LOP_SPUT_BOOLEAN_resolve:
8736    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8737    EXPORT_PC()                         @ resolve() could throw, so export now
8738    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8739    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8740    cmp     r0, #0                      @ success?
8741    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8742    b       common_exceptionThrown      @ no, handle exception
8743
8744
8745/* continuation for OP_SPUT_BYTE */
8746
8747    /*
8748     * Continuation if the field has not yet been resolved.
8749     *  r1: BBBB field ref
8750     */
8751.LOP_SPUT_BYTE_resolve:
8752    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8753    EXPORT_PC()                         @ resolve() could throw, so export now
8754    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8755    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8756    cmp     r0, #0                      @ success?
8757    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8758    b       common_exceptionThrown      @ no, handle exception
8759
8760
8761/* continuation for OP_SPUT_CHAR */
8762
8763    /*
8764     * Continuation if the field has not yet been resolved.
8765     *  r1: BBBB field ref
8766     */
8767.LOP_SPUT_CHAR_resolve:
8768    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8769    EXPORT_PC()                         @ resolve() could throw, so export now
8770    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8771    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8772    cmp     r0, #0                      @ success?
8773    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8774    b       common_exceptionThrown      @ no, handle exception
8775
8776
8777/* continuation for OP_SPUT_SHORT */
8778
8779    /*
8780     * Continuation if the field has not yet been resolved.
8781     *  r1: BBBB field ref
8782     */
8783.LOP_SPUT_SHORT_resolve:
8784    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8785    EXPORT_PC()                         @ resolve() could throw, so export now
8786    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8787    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8788    cmp     r0, #0                      @ success?
8789    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8790    b       common_exceptionThrown      @ no, handle exception
8791
8792
8793/* continuation for OP_INVOKE_VIRTUAL */
8794
8795    /*
8796     * At this point:
8797     *  r0 = resolved base method
8798     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8799     */
8800.LOP_INVOKE_VIRTUAL_continue:
8801    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8802    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8803    cmp     r1, #0                      @ is "this" null?
8804    beq     common_errNullObject        @ null "this", throw exception
8805    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8806    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8807    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8808    bl      common_invokeMethodNoRange @ continue on
8809
8810
8811/* continuation for OP_INVOKE_SUPER */
8812
8813    /*
8814     * At this point:
8815     *  r0 = resolved base method
8816     *  r9 = method->clazz
8817     */
8818.LOP_INVOKE_SUPER_continue:
8819    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8820    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8821    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8822    EXPORT_PC()                         @ must export for invoke
8823    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8824    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8825    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8826    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8827    bl      common_invokeMethodNoRange @ continue on
8828
8829.LOP_INVOKE_SUPER_resolve:
8830    mov     r0, r9                      @ r0<- method->clazz
8831    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8832    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8833    cmp     r0, #0                      @ got null?
8834    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8835    b       common_exceptionThrown      @ yes, handle exception
8836
8837    /*
8838     * Throw a NoSuchMethodError with the method name as the message.
8839     *  r0 = resolved base method
8840     */
8841.LOP_INVOKE_SUPER_nsm:
8842    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8843    b       common_errNoSuchMethod
8844
8845
8846/* continuation for OP_INVOKE_DIRECT */
8847
8848    /*
8849     * On entry:
8850     *  r1 = reference (BBBB or CCCC)
8851     *  r10 = "this" register
8852     */
8853.LOP_INVOKE_DIRECT_resolve:
8854    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8855    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8856    mov     r2, #METHOD_DIRECT          @ resolver method type
8857    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8858    cmp     r0, #0                      @ got null?
8859    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8860    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8861    b       common_exceptionThrown      @ yes, handle exception
8862
8863
8864/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8865
8866    /*
8867     * At this point:
8868     *  r0 = resolved base method
8869     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8870     */
8871.LOP_INVOKE_VIRTUAL_RANGE_continue:
8872    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8873    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8874    cmp     r1, #0                      @ is "this" null?
8875    beq     common_errNullObject        @ null "this", throw exception
8876    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8877    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8878    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8879    bl      common_invokeMethodRange @ continue on
8880
8881
8882/* continuation for OP_INVOKE_SUPER_RANGE */
8883
8884    /*
8885     * At this point:
8886     *  r0 = resolved base method
8887     *  r9 = method->clazz
8888     */
8889.LOP_INVOKE_SUPER_RANGE_continue:
8890    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8891    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8892    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8893    EXPORT_PC()                         @ must export for invoke
8894    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8895    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8896    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8897    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8898    bl      common_invokeMethodRange @ continue on
8899
8900.LOP_INVOKE_SUPER_RANGE_resolve:
8901    mov     r0, r9                      @ r0<- method->clazz
8902    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8903    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8904    cmp     r0, #0                      @ got null?
8905    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8906    b       common_exceptionThrown      @ yes, handle exception
8907
8908    /*
8909     * Throw a NoSuchMethodError with the method name as the message.
8910     *  r0 = resolved base method
8911     */
8912.LOP_INVOKE_SUPER_RANGE_nsm:
8913    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8914    b       common_errNoSuchMethod
8915
8916
8917/* continuation for OP_INVOKE_DIRECT_RANGE */
8918
8919    /*
8920     * On entry:
8921     *  r1 = reference (BBBB or CCCC)
8922     *  r10 = "this" register
8923     */
8924.LOP_INVOKE_DIRECT_RANGE_resolve:
8925    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8926    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8927    mov     r2, #METHOD_DIRECT          @ resolver method type
8928    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8929    cmp     r0, #0                      @ got null?
8930    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8931    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8932    b       common_exceptionThrown      @ yes, handle exception
8933
8934
8935/* continuation for OP_FLOAT_TO_LONG */
8936/*
8937 * Convert the float in r0 to a long in r0/r1.
8938 *
8939 * We have to clip values to long min/max per the specification.  The
8940 * expected common case is a "reasonable" value that converts directly
8941 * to modest integer.  The EABI convert function isn't doing this for us.
8942 */
8943f2l_doconv:
8944    stmfd   sp!, {r4, lr}
8945    mov     r1, #0x5f000000             @ (float)maxlong
8946    mov     r4, r0
8947    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8948    cmp     r0, #0                      @ nonzero == yes
8949    mvnne   r0, #0                      @ return maxlong (7fffffff)
8950    mvnne   r1, #0x80000000
8951    ldmnefd sp!, {r4, pc}
8952
8953    mov     r0, r4                      @ recover arg
8954    mov     r1, #0xdf000000             @ (float)minlong
8955    bl      __aeabi_fcmple              @ is arg <= minlong?
8956    cmp     r0, #0                      @ nonzero == yes
8957    movne   r0, #0                      @ return minlong (80000000)
8958    movne   r1, #0x80000000
8959    ldmnefd sp!, {r4, pc}
8960
8961    mov     r0, r4                      @ recover arg
8962    mov     r1, r4
8963    bl      __aeabi_fcmpeq              @ is arg == self?
8964    cmp     r0, #0                      @ zero == no
8965    moveq   r1, #0                      @ return zero for NaN
8966    ldmeqfd sp!, {r4, pc}
8967
8968    mov     r0, r4                      @ recover arg
8969    bl      __aeabi_f2lz                @ convert float to long
8970    ldmfd   sp!, {r4, pc}
8971
8972
8973/* continuation for OP_DOUBLE_TO_LONG */
8974/*
8975 * Convert the double in r0/r1 to a long in r0/r1.
8976 *
8977 * We have to clip values to long min/max per the specification.  The
8978 * expected common case is a "reasonable" value that converts directly
8979 * to modest integer.  The EABI convert function isn't doing this for us.
8980 */
8981d2l_doconv:
8982    stmfd   sp!, {r4, r5, lr}           @ save regs
8983    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8984    add     r3, #0x00e00000             @  0x43e00000
8985    mov     r2, #0                      @ maxlong, as a double (low word)
8986    sub     sp, sp, #4                  @ align for EABI
8987    mov     r4, r0                      @ save a copy of r0
8988    mov     r5, r1                      @  and r1
8989    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8990    cmp     r0, #0                      @ nonzero == yes
8991    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8992    mvnne   r1, #0x80000000
8993    bne     1f
8994
8995    mov     r0, r4                      @ recover arg
8996    mov     r1, r5
8997    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8998    add     r3, #0x00e00000             @  0xc3e00000
8999    mov     r2, #0                      @ minlong, as a double (low word)
9000    bl      __aeabi_dcmple              @ is arg <= minlong?
9001    cmp     r0, #0                      @ nonzero == yes
9002    movne   r0, #0                      @ return minlong (8000000000000000)
9003    movne   r1, #0x80000000
9004    bne     1f
9005
9006    mov     r0, r4                      @ recover arg
9007    mov     r1, r5
9008    mov     r2, r4                      @ compare against self
9009    mov     r3, r5
9010    bl      __aeabi_dcmpeq              @ is arg == self?
9011    cmp     r0, #0                      @ zero == no
9012    moveq   r1, #0                      @ return zero for NaN
9013    beq     1f
9014
9015    mov     r0, r4                      @ recover arg
9016    mov     r1, r5
9017    bl      __aeabi_d2lz                @ convert double to long
9018
90191:
9020    add     sp, sp, #4
9021    ldmfd   sp!, {r4, r5, pc}
9022
9023
9024/* continuation for OP_MUL_LONG */
9025
9026.LOP_MUL_LONG_finish:
9027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9028    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9029    GOTO_OPCODE(ip)                     @ jump to next instruction
9030
9031
9032/* continuation for OP_SHL_LONG */
9033
9034.LOP_SHL_LONG_finish:
9035    mov     r0, r0, asl r2              @  r0<- r0 << r2
9036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9037    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9038    GOTO_OPCODE(ip)                     @ jump to next instruction
9039
9040
9041/* continuation for OP_SHR_LONG */
9042
9043.LOP_SHR_LONG_finish:
9044    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9045    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9046    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9047    GOTO_OPCODE(ip)                     @ jump to next instruction
9048
9049
9050/* continuation for OP_USHR_LONG */
9051
9052.LOP_USHR_LONG_finish:
9053    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9054    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9055    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9056    GOTO_OPCODE(ip)                     @ jump to next instruction
9057
9058
9059/* continuation for OP_SHL_LONG_2ADDR */
9060
9061.LOP_SHL_LONG_2ADDR_finish:
9062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9063    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9064    GOTO_OPCODE(ip)                     @ jump to next instruction
9065
9066
9067/* continuation for OP_SHR_LONG_2ADDR */
9068
9069.LOP_SHR_LONG_2ADDR_finish:
9070    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9071    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9072    GOTO_OPCODE(ip)                     @ jump to next instruction
9073
9074
9075/* continuation for OP_USHR_LONG_2ADDR */
9076
9077.LOP_USHR_LONG_2ADDR_finish:
9078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9079    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9080    GOTO_OPCODE(ip)                     @ jump to next instruction
9081
9082
9083/* continuation for OP_IGET_WIDE_VOLATILE */
9084
9085    /*
9086     * Currently:
9087     *  r0 holds resolved field
9088     *  r9 holds object
9089     */
9090.LOP_IGET_WIDE_VOLATILE_finish:
9091    cmp     r9, #0                      @ check object for null
9092    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9093    beq     common_errNullObject        @ object was null
9094    .if 1
9095    add     r0, r9, r3                  @ r0<- address of field
9096    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
9097    .else
9098    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9099    .endif
9100    mov     r2, rINST, lsr #8           @ r2<- A+
9101    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9102    and     r2, r2, #15                 @ r2<- A
9103    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9105    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9106    GOTO_OPCODE(ip)                     @ jump to next instruction
9107
9108
9109/* continuation for OP_IPUT_WIDE_VOLATILE */
9110
9111    /*
9112     * Currently:
9113     *  r0 holds resolved field
9114     *  r9 holds object
9115     */
9116.LOP_IPUT_WIDE_VOLATILE_finish:
9117    mov     r2, rINST, lsr #8           @ r2<- A+
9118    cmp     r9, #0                      @ check object for null
9119    and     r2, r2, #15                 @ r2<- A
9120    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9121    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9122    beq     common_errNullObject        @ object was null
9123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9124    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9125    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9126    .if 1
9127    add     r2, r9, r3                  @ r2<- target address
9128    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
9129    .else
9130    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9131    .endif
9132    GOTO_OPCODE(r10)                    @ jump to next instruction
9133
9134
9135/* continuation for OP_SGET_WIDE_VOLATILE */
9136
9137    /*
9138     * Continuation if the field has not yet been resolved.
9139     *  r1: BBBB field ref
9140     *
9141     * Returns StaticField pointer in r0.
9142     */
9143.LOP_SGET_WIDE_VOLATILE_resolve:
9144    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9145    EXPORT_PC()                         @ resolve() could throw, so export now
9146    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9147    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9148    cmp     r0, #0                      @ success?
9149    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9150    b       common_exceptionThrown      @ no, handle exception
9151
9152
9153/* continuation for OP_SPUT_WIDE_VOLATILE */
9154
9155    /*
9156     * Continuation if the field has not yet been resolved.
9157     *  r1: BBBB field ref
9158     *  r9: &fp[AA]
9159     *
9160     * Returns StaticField pointer in r2.
9161     */
9162.LOP_SPUT_WIDE_VOLATILE_resolve:
9163    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9164    EXPORT_PC()                         @ resolve() could throw, so export now
9165    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9166    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9167    cmp     r0, #0                      @ success?
9168    mov     r2, r0                      @ copy to r2
9169    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9170    b       common_exceptionThrown      @ no, handle exception
9171
9172
9173/* continuation for OP_EXECUTE_INLINE */
9174
9175    /*
9176     * Extract args, call function.
9177     *  r0 = #of args (0-4)
9178     *  r10 = call index
9179     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9180     *
9181     * Other ideas:
9182     * - Use a jump table from the main piece to jump directly into the
9183     *   AND/LDR pairs.  Costs a data load, saves a branch.
9184     * - Have five separate pieces that do the loading, so we can work the
9185     *   interleave a little better.  Increases code size.
9186     */
9187.LOP_EXECUTE_INLINE_continue:
9188    rsb     r0, r0, #4                  @ r0<- 4-r0
9189    FETCH(r9, 2)                        @ r9<- FEDC
9190    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9191    bl      common_abort                @ (skipped due to ARM prefetch)
91924:  and     ip, r9, #0xf000             @ isolate F
9193    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
91943:  and     ip, r9, #0x0f00             @ isolate E
9195    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
91962:  and     ip, r9, #0x00f0             @ isolate D
9197    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
91981:  and     ip, r9, #0x000f             @ isolate C
9199    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92000:
9201    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9202    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9203    @ (not reached)
9204
9205.LOP_EXECUTE_INLINE_table:
9206    .word   gDvmInlineOpsTable
9207
9208
9209/* continuation for OP_EXECUTE_INLINE_RANGE */
9210
9211    /*
9212     * Extract args, call function.
9213     *  r0 = #of args (0-4)
9214     *  r10 = call index
9215     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9216     */
9217.LOP_EXECUTE_INLINE_RANGE_continue:
9218    rsb     r0, r0, #4                  @ r0<- 4-r0
9219    FETCH(r9, 2)                        @ r9<- CCCC
9220    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9221    bl      common_abort                @ (skipped due to ARM prefetch)
92224:  add     ip, r9, #3                  @ base+3
9223    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92243:  add     ip, r9, #2                  @ base+2
9225    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92262:  add     ip, r9, #1                  @ base+1
9227    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92281:  add     ip, r9, #0                  @ (nop)
9229    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92300:
9231    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9232    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9233    @ (not reached)
9234
9235.LOP_EXECUTE_INLINE_RANGE_table:
9236    .word   gDvmInlineOpsTable
9237
9238
9239    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9240    .global dvmAsmSisterEnd
9241dvmAsmSisterEnd:
9242
9243/* File: armv5te/footer.S */
9244
9245/*
9246 * ===========================================================================
9247 *  Common subroutines and data
9248 * ===========================================================================
9249 */
9250
9251
9252
9253    .text
9254    .align  2
9255
9256#if defined(WITH_JIT)
9257#if defined(WITH_SELF_VERIFICATION)
9258    .global dvmJitToInterpPunt
9259dvmJitToInterpPunt:
9260    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9261    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9262    mov    r3, #0
9263    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9264    b      jitSVShadowRunEnd            @ doesn't return
9265
9266    .global dvmJitToInterpSingleStep
9267dvmJitToInterpSingleStep:
9268    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9269    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9270    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9271    b      jitSVShadowRunEnd            @ doesn't return
9272
9273    .global dvmJitToInterpTraceSelectNoChain
9274dvmJitToInterpTraceSelectNoChain:
9275    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9276    mov    r0,rPC                       @ pass our target PC
9277    mov    r2,#kSVSTraceSelectNoChain   @ r2<- interpreter entry point
9278    mov    r3, #0
9279    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9280    b      jitSVShadowRunEnd            @ doesn't return
9281
9282    .global dvmJitToInterpTraceSelect
9283dvmJitToInterpTraceSelect:
9284    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9285    ldr    r0,[lr, #-1]                 @ pass our target PC
9286    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9287    mov    r3, #0
9288    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9289    b      jitSVShadowRunEnd            @ doesn't return
9290
9291    .global dvmJitToInterpBackwardBranch
9292dvmJitToInterpBackwardBranch:
9293    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9294    ldr    r0,[lr, #-1]                 @ pass our target PC
9295    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9296    mov    r3, #0
9297    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9298    b      jitSVShadowRunEnd            @ doesn't return
9299
9300    .global dvmJitToInterpNormal
9301dvmJitToInterpNormal:
9302    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9303    ldr    r0,[lr, #-1]                 @ pass our target PC
9304    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9305    mov    r3, #0
9306    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9307    b      jitSVShadowRunEnd            @ doesn't return
9308
9309    .global dvmJitToInterpNoChain
9310dvmJitToInterpNoChain:
9311    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9312    mov    r0,rPC                       @ pass our target PC
9313    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9314    mov    r3, #0
9315    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9316    b      jitSVShadowRunEnd            @ doesn't return
9317#else
9318/*
9319 * Return from the translation cache to the interpreter when the compiler is
9320 * having issues translating/executing a Dalvik instruction. We have to skip
9321 * the code cache lookup otherwise it is possible to indefinitely bouce
9322 * between the interpreter and the code cache if the instruction that fails
9323 * to be compiled happens to be at a trace start.
9324 */
9325    .global dvmJitToInterpPunt
9326dvmJitToInterpPunt:
9327    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9328    mov    rPC, r0
9329#if defined(WITH_JIT_TUNING)
9330    mov    r0,lr
9331    bl     dvmBumpPunt;
9332#endif
9333    EXPORT_PC()
9334    mov    r0, #0
9335    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9336    adrl   rIBASE, dvmAsmInstructionStart
9337    FETCH_INST()
9338    GET_INST_OPCODE(ip)
9339    GOTO_OPCODE(ip)
9340
9341/*
9342 * Return to the interpreter to handle a single instruction.
9343 * On entry:
9344 *    r0 <= PC
9345 *    r1 <= PC of resume instruction
9346 *    lr <= resume point in translation
9347 */
9348    .global dvmJitToInterpSingleStep
9349dvmJitToInterpSingleStep:
9350    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9351    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9352    mov    r1,#kInterpEntryInstr
9353    @ enum is 4 byte in aapcs-EABI
9354    str    r1, [rGLUE, #offGlue_entryPoint]
9355    mov    rPC,r0
9356    EXPORT_PC()
9357
9358    adrl   rIBASE, dvmAsmInstructionStart
9359    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9360    str    r2,[rGLUE,#offGlue_jitState]
9361    mov    r1,#1                  @ set changeInterp to bail to debug interp
9362    b      common_gotoBail
9363
9364/*
9365 * Return from the translation cache and immediately request
9366 * a translation for the exit target.  Commonly used for callees.
9367 */
9368    .global dvmJitToInterpTraceSelectNoChain
9369dvmJitToInterpTraceSelectNoChain:
9370#if defined(WITH_JIT_TUNING)
9371    bl     dvmBumpNoChain
9372#endif
9373    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9374    mov    r0,rPC
9375    bl     dvmJitGetCodeAddr        @ Is there a translation?
9376    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9377    mov    r1, rPC                  @ arg1 of translation may need this
9378    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9379    cmp    r0,#0
9380    bxne   r0                       @ continue native execution if so
9381    b      2f
9382
9383/*
9384 * Return from the translation cache and immediately request
9385 * a translation for the exit target.  Commonly used following
9386 * invokes.
9387 */
9388    .global dvmJitToInterpTraceSelect
9389dvmJitToInterpTraceSelect:
9390    ldr    rPC,[lr, #-1]           @ get our target PC
9391    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9392    add    rINST,lr,#-5            @ save start of chain branch
9393    add    rINST, #-4              @  .. which is 9 bytes back
9394    mov    r0,rPC
9395    bl     dvmJitGetCodeAddr       @ Is there a translation?
9396    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9397    cmp    r0,#0
9398    beq    2f
9399    mov    r1,rINST
9400    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9401    mov    r1, rPC                  @ arg1 of translation may need this
9402    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9403    cmp    r0,#0                    @ successful chain?
9404    bxne   r0                       @ continue native execution
9405    b      toInterpreter            @ didn't chain - resume with interpreter
9406
9407/* No translation, so request one if profiling isn't disabled*/
94082:
9409    adrl   rIBASE, dvmAsmInstructionStart
9410    GET_JIT_PROF_TABLE(r0)
9411    FETCH_INST()
9412    cmp    r0, #0
9413    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9414    bne    common_selectTrace
9415    GET_INST_OPCODE(ip)
9416    GOTO_OPCODE(ip)
9417
9418/*
9419 * Return from the translation cache to the interpreter.
9420 * The return was done with a BLX from thumb mode, and
9421 * the following 32-bit word contains the target rPC value.
9422 * Note that lr (r14) will have its low-order bit set to denote
9423 * its thumb-mode origin.
9424 *
9425 * We'll need to stash our lr origin away, recover the new
9426 * target and then check to see if there is a translation available
9427 * for our new target.  If so, we do a translation chain and
9428 * go back to native execution.  Otherwise, it's back to the
9429 * interpreter (after treating this entry as a potential
9430 * trace start).
9431 */
9432    .global dvmJitToInterpNormal
9433dvmJitToInterpNormal:
9434    ldr    rPC,[lr, #-1]           @ get our target PC
9435    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9436    add    rINST,lr,#-5            @ save start of chain branch
9437    add    rINST,#-4               @ .. which is 9 bytes back
9438#if defined(WITH_JIT_TUNING)
9439    bl     dvmBumpNormal
9440#endif
9441    mov    r0,rPC
9442    bl     dvmJitGetCodeAddr        @ Is there a translation?
9443    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9444    cmp    r0,#0
9445    beq    toInterpreter            @ go if not, otherwise do chain
9446    mov    r1,rINST
9447    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9448    mov    r1, rPC                  @ arg1 of translation may need this
9449    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9450    cmp    r0,#0                    @ successful chain?
9451    bxne   r0                       @ continue native execution
9452    b      toInterpreter            @ didn't chain - resume with interpreter
9453
9454/*
9455 * Return from the translation cache to the interpreter to do method invocation.
9456 * Check if translation exists for the callee, but don't chain to it.
9457 */
9458    .global dvmJitToInterpNoChain
9459dvmJitToInterpNoChain:
9460#if defined(WITH_JIT_TUNING)
9461    bl     dvmBumpNoChain
9462#endif
9463    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9464    mov    r0,rPC
9465    bl     dvmJitGetCodeAddr        @ Is there a translation?
9466    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9467    mov    r1, rPC                  @ arg1 of translation may need this
9468    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9469    cmp    r0,#0
9470    bxne   r0                       @ continue native execution if so
9471#endif
9472
9473/*
9474 * No translation, restore interpreter regs and start interpreting.
9475 * rGLUE & rFP were preserved in the translated code, and rPC has
9476 * already been restored by the time we get here.  We'll need to set
9477 * up rIBASE & rINST, and load the address of the JitTable into r0.
9478 */
9479toInterpreter:
9480    EXPORT_PC()
9481    adrl   rIBASE, dvmAsmInstructionStart
9482    FETCH_INST()
9483    GET_JIT_PROF_TABLE(r0)
9484    @ NOTE: intended fallthrough
9485/*
9486 * Common code to update potential trace start counter, and initiate
9487 * a trace-build if appropriate.  On entry, rPC should point to the
9488 * next instruction to execute, and rINST should be already loaded with
9489 * the next opcode word, and r0 holds a pointer to the jit profile
9490 * table (pJitProfTable).
9491 */
9492common_testUpdateProfile:
9493    cmp     r0,#0
9494    GET_INST_OPCODE(ip)
9495    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9496
9497common_updateProfile:
9498    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9499    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9500    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9501    GET_INST_OPCODE(ip)
9502    subs    r1,r1,#1           @ decrement counter
9503    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9504    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9505
9506/*
9507 * Here, we switch to the debug interpreter to request
9508 * trace selection.  First, though, check to see if there
9509 * is already a native translation in place (and, if so,
9510 * jump to it now).
9511 */
9512    GET_JIT_THRESHOLD(r1)
9513    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9514    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9515    EXPORT_PC()
9516    mov     r0,rPC
9517    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9518    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9519    mov     r1, rPC                     @ arg1 of translation may need this
9520    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9521    cmp     r0,#0
9522#if !defined(WITH_SELF_VERIFICATION)
9523    bxne    r0                          @ jump to the translation
9524    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9525    @ fall-through to common_selectTrace
9526#else
9527    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9528    beq     common_selectTrace
9529    /*
9530     * At this point, we have a target translation.  However, if
9531     * that translation is actually the interpret-only pseudo-translation
9532     * we want to treat it the same as no translation.
9533     */
9534    mov     r10, r0                     @ save target
9535    bl      dvmCompilerGetInterpretTemplate
9536    cmp     r0, r10                     @ special case?
9537    bne     jitSVShadowRunStart         @ set up self verification shadow space
9538    GET_INST_OPCODE(ip)
9539    GOTO_OPCODE(ip)
9540    /* no return */
9541#endif
9542
9543/*
9544 * On entry:
9545 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9546 */
9547common_selectTrace:
9548    str     r2,[rGLUE,#offGlue_jitState]
9549    mov     r2,#kInterpEntryInstr       @ normal entry reason
9550    str     r2,[rGLUE,#offGlue_entryPoint]
9551    mov     r1,#1                       @ set changeInterp
9552    b       common_gotoBail
9553
9554#if defined(WITH_SELF_VERIFICATION)
9555/*
9556 * Save PC and registers to shadow memory for self verification mode
9557 * before jumping to native translation.
9558 * On entry:
9559 *    rPC, rFP, rGLUE: the values that they should contain
9560 *    r10: the address of the target translation.
9561 */
9562jitSVShadowRunStart:
9563    mov     r0,rPC                      @ r0<- program counter
9564    mov     r1,rFP                      @ r1<- frame pointer
9565    mov     r2,rGLUE                    @ r2<- InterpState pointer
9566    mov     r3,r10                      @ r3<- target translation
9567    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9568    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9569    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9570    bx      r10                         @ jump to the translation
9571
9572/*
9573 * Restore PC, registers, and interpState to original values
9574 * before jumping back to the interpreter.
9575 */
9576jitSVShadowRunEnd:
9577    mov    r1,rFP                        @ pass ending fp
9578    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9579    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9580    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9581    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9582    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9583    cmp    r1,#0                         @ check for punt condition
9584    beq    1f
9585    mov    r2,#kJitSelfVerification      @ ask for self verification
9586    str    r2,[rGLUE,#offGlue_jitState]
9587    mov    r2,#kInterpEntryInstr         @ normal entry reason
9588    str    r2,[rGLUE,#offGlue_entryPoint]
9589    mov    r1,#1                         @ set changeInterp
9590    b      common_gotoBail
9591
95921:                                       @ exit to interpreter without check
9593    EXPORT_PC()
9594    adrl   rIBASE, dvmAsmInstructionStart
9595    FETCH_INST()
9596    GET_INST_OPCODE(ip)
9597    GOTO_OPCODE(ip)
9598#endif
9599
9600#endif
9601
9602/*
9603 * Common code when a backward branch is taken.
9604 *
9605 * TODO: we could avoid a branch by just setting r0 and falling through
9606 * into the common_periodicChecks code, and having a test on r0 at the
9607 * end determine if we should return to the caller or update & branch to
9608 * the next instr.
9609 *
9610 * On entry:
9611 *  r9 is PC adjustment *in bytes*
9612 */
9613common_backwardBranch:
9614    mov     r0, #kInterpEntryInstr
9615    bl      common_periodicChecks
9616#if defined(WITH_JIT)
9617    GET_JIT_PROF_TABLE(r0)
9618    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9619    cmp     r0,#0
9620    bne     common_updateProfile
9621    GET_INST_OPCODE(ip)
9622    GOTO_OPCODE(ip)
9623#else
9624    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9626    GOTO_OPCODE(ip)                     @ jump to next instruction
9627#endif
9628
9629
9630/*
9631 * Need to see if the thread needs to be suspended or debugger/profiler
9632 * activity has begun.  If so, we suspend the thread or side-exit to
9633 * the debug interpreter as appropriate.
9634 *
9635 * The common case is no activity on any of these, so we want to figure
9636 * that out quickly.  If something is up, we can then sort out what.
9637 *
9638 * We want to be fast if the VM was built without debugger or profiler
9639 * support, but we also need to recognize that the system is usually
9640 * shipped with both of these enabled.
9641 *
9642 * TODO: reduce this so we're just checking a single location.
9643 *
9644 * On entry:
9645 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9646 *  r9 is trampoline PC adjustment *in bytes*
9647 */
9648common_periodicChecks:
9649    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9650
9651#if defined(WITH_DEBUGGER)
9652    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9653#endif
9654#if defined(WITH_PROFILER)
9655    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9656#endif
9657
9658    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9659
9660#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9661    cmp     r1, #0                      @ debugger enabled?
9662    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9663    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9664    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9665    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9666#elif defined(WITH_DEBUGGER)
9667    cmp     r1, #0                      @ debugger enabled?
9668    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9669    orrsne  ip, ip, r1                  @ yes, ip<- suspend | debugger; set Z
9670    @ (if not enabled, Z was set by test for r1==0, which is what we want)
9671#elif defined (WITH_PROFILER)
9672    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9673    orrs    ip, ip, r2                  @ ip<- suspendCount | activeProfilers
9674#else
9675    cmp     ip, #0                      @ not ORing anything in; set Z
9676#endif
9677
9678    bxeq    lr                          @ all zero, return
9679
9680    /*
9681     * One or more interesting events have happened.  Figure out what.
9682     *
9683     * If debugging or profiling are compiled in, we need to disambiguate.
9684     *
9685     * r0 still holds the reentry type.
9686     */
9687#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9688    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9689    cmp     ip, #0                      @ want suspend?
9690    beq     1f                          @ no, must be debugger/profiler
9691#endif
9692
9693    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9694#if defined(WITH_JIT)
9695    /*
9696     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9697     * doubles as the Jit's on/off switch.
9698     */
9699    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9700    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9701    ldr     r3, [r3] @ r3 <- pJitProfTable
9702    EXPORT_PC()                         @ need for precise GC
9703    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9704#else
9705    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9706    EXPORT_PC()                         @ need for precise GC
9707#endif
9708    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9709    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9710
9711#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9712
9713    /*
9714     * Reload the debugger/profiler enable flags.  We're checking to see
9715     * if either of these got set while we were suspended.
9716     *
9717     * We can't really avoid the #ifdefs here, because the fields don't
9718     * exist when the feature is disabled.
9719     */
9720#if defined(WITH_DEBUGGER)
9721    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9722    cmp     r1, #0                      @ debugger enabled?
9723    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9724#else
9725    mov     r1, #0
9726#endif
9727#if defined(WITH_PROFILER)
9728    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9729    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9730#else
9731    mov     r2, #0
9732#endif
9733
9734    orrs    r1, r1, r2
9735    beq     2f
9736
97371:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9738    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9739    add     rPC, rPC, r9                @ update rPC
9740    mov     r1, #1                      @ "want switch" = true
9741    b       common_gotoBail             @ side exit
9742
9743#endif /*WITH_DEBUGGER || WITH_PROFILER*/
9744
97452:
9746    bx      lr                          @ nothing to do, return
9747
9748
9749/*
9750 * The equivalent of "goto bail", this calls through the "bail handler".
9751 *
9752 * State registers will be saved to the "glue" area before bailing.
9753 *
9754 * On entry:
9755 *  r1 is "bool changeInterp", indicating if we want to switch to the
9756 *     other interpreter or just bail all the way out
9757 */
9758common_gotoBail:
9759    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9760    mov     r0, rGLUE                   @ r0<- glue ptr
9761    b       dvmMterpStdBail             @ call(glue, changeInterp)
9762
9763    @add     r1, r1, #1                  @ using (boolean+1)
9764    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9765    @bl      _longjmp                    @ does not return
9766    @bl      common_abort
9767
9768
9769/*
9770 * Common code for method invocation with range.
9771 *
9772 * On entry:
9773 *  r0 is "Method* methodToCall", the method we're trying to call
9774 */
9775common_invokeMethodRange:
9776.LinvokeNewRange:
9777    @ prepare to copy args to "outs" area of current frame
9778    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9779    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9780    beq     .LinvokeArgsDone            @ if no args, skip the rest
9781    FETCH(r1, 2)                        @ r1<- CCCC
9782
9783    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9784    @ (very few methods have > 10 args; could unroll for common cases)
9785    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9786    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9787    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
97881:  ldr     r1, [r3], #4                @ val = *fp++
9789    subs    r2, r2, #1                  @ count--
9790    str     r1, [r10], #4               @ *outs++ = val
9791    bne     1b                          @ ...while count != 0
9792    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9793    b       .LinvokeArgsDone
9794
9795/*
9796 * Common code for method invocation without range.
9797 *
9798 * On entry:
9799 *  r0 is "Method* methodToCall", the method we're trying to call
9800 */
9801common_invokeMethodNoRange:
9802.LinvokeNewNoRange:
9803    @ prepare to copy args to "outs" area of current frame
9804    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9805    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9806    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9807    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9808    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9809    beq     .LinvokeArgsDone
9810
9811    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9812.LinvokeNonRange:
9813    rsb     r2, r2, #5                  @ r2<- 5-r2
9814    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9815    bl      common_abort                @ (skipped due to ARM prefetch)
98165:  and     ip, rINST, #0x0f00          @ isolate A
9817    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9818    mov     r0, r0                      @ nop
9819    str     r2, [r10, #-4]!             @ *--outs = vA
98204:  and     ip, r1, #0xf000             @ isolate G
9821    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9822    mov     r0, r0                      @ nop
9823    str     r2, [r10, #-4]!             @ *--outs = vG
98243:  and     ip, r1, #0x0f00             @ isolate F
9825    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9826    mov     r0, r0                      @ nop
9827    str     r2, [r10, #-4]!             @ *--outs = vF
98282:  and     ip, r1, #0x00f0             @ isolate E
9829    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9830    mov     r0, r0                      @ nop
9831    str     r2, [r10, #-4]!             @ *--outs = vE
98321:  and     ip, r1, #0x000f             @ isolate D
9833    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9834    mov     r0, r0                      @ nop
9835    str     r2, [r10, #-4]!             @ *--outs = vD
98360:  @ fall through to .LinvokeArgsDone
9837
9838.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9839    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9840    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9841    @ find space for the new stack frame, check for overflow
9842    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9843    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9844    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9845@    bl      common_dumpRegs
9846    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9847    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9848    cmp     r3, r9                      @ bottom < interpStackEnd?
9849    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9850    blo     .LstackOverflow             @ yes, this frame will overflow stack
9851
9852    @ set up newSaveArea
9853#ifdef EASY_GDB
9854    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9855    str     ip, [r10, #offStackSaveArea_prevSave]
9856#endif
9857    str     rFP, [r10, #offStackSaveArea_prevFrame]
9858    str     rPC, [r10, #offStackSaveArea_savedPc]
9859#if defined(WITH_JIT)
9860    mov     r9, #0
9861    str     r9, [r10, #offStackSaveArea_returnAddr]
9862#endif
9863    str     r0, [r10, #offStackSaveArea_method]
9864    tst     r3, #ACC_NATIVE
9865    bne     .LinvokeNative
9866
9867    /*
9868    stmfd   sp!, {r0-r3}
9869    bl      common_printNewline
9870    mov     r0, rFP
9871    mov     r1, #0
9872    bl      dvmDumpFp
9873    ldmfd   sp!, {r0-r3}
9874    stmfd   sp!, {r0-r3}
9875    mov     r0, r1
9876    mov     r1, r10
9877    bl      dvmDumpFp
9878    bl      common_printNewline
9879    ldmfd   sp!, {r0-r3}
9880    */
9881
9882    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9883    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9884    mov     rPC, r2                         @ publish new rPC
9885    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9886
9887    @ Update "glue" values for the new method
9888    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9889    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9890    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9891#if defined(WITH_JIT)
9892    GET_JIT_PROF_TABLE(r0)
9893    mov     rFP, r1                         @ fp = newFp
9894    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9895    mov     rINST, r9                       @ publish new rINST
9896    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9897    cmp     r0,#0
9898    bne     common_updateProfile
9899    GOTO_OPCODE(ip)                         @ jump to next instruction
9900#else
9901    mov     rFP, r1                         @ fp = newFp
9902    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9903    mov     rINST, r9                       @ publish new rINST
9904    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9905    GOTO_OPCODE(ip)                         @ jump to next instruction
9906#endif
9907
9908.LinvokeNative:
9909    @ Prep for the native call
9910    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9911    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9912    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9913    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9914    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9915    mov     r9, r3                      @ r9<- glue->self (preserve)
9916
9917    mov     r2, r0                      @ r2<- methodToCall
9918    mov     r0, r1                      @ r0<- newFp (points to args)
9919    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9920
9921#ifdef ASSIST_DEBUGGER
9922    /* insert fake function header to help gdb find the stack frame */
9923    b       .Lskip
9924    .type   dalvik_mterp, %function
9925dalvik_mterp:
9926    .fnstart
9927    MTERP_ENTRY1
9928    MTERP_ENTRY2
9929.Lskip:
9930#endif
9931
9932    @mov     lr, pc                      @ set return addr
9933    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9934    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9935
9936#if defined(WITH_JIT)
9937    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9938#endif
9939
9940    @ native return; r9=self, r10=newSaveArea
9941    @ equivalent to dvmPopJniLocals
9942    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9943    ldr     r1, [r9, #offThread_exception] @ check for exception
9944#if defined(WITH_JIT)
9945    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9946#endif
9947    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9948    cmp     r1, #0                      @ null?
9949    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9950#if defined(WITH_JIT)
9951    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9952#endif
9953    bne     common_exceptionThrown      @ no, handle exception
9954
9955    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9956    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9957    GOTO_OPCODE(ip)                     @ jump to next instruction
9958
9959.LstackOverflow:    @ r0=methodToCall
9960    mov     r1, r0                      @ r1<- methodToCall
9961    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9962    bl      dvmHandleStackOverflow
9963    b       common_exceptionThrown
9964#ifdef ASSIST_DEBUGGER
9965    .fnend
9966#endif
9967
9968
9969    /*
9970     * Common code for method invocation, calling through "glue code".
9971     *
9972     * TODO: now that we have range and non-range invoke handlers, this
9973     *       needs to be split into two.  Maybe just create entry points
9974     *       that set r9 and jump here?
9975     *
9976     * On entry:
9977     *  r0 is "Method* methodToCall", the method we're trying to call
9978     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9979     */
9980     .if    0
9981.LinvokeOld:
9982    sub     sp, sp, #8                  @ space for args + pad
9983    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9984    mov     r2, r0                      @ A2<- methodToCall
9985    mov     r0, rGLUE                   @ A0<- glue
9986    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9987    mov     r1, r9                      @ A1<- methodCallRange
9988    mov     r3, rINST, lsr #8           @ A3<- AA
9989    str     ip, [sp, #0]                @ A4<- ip
9990    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9991    add     sp, sp, #8                  @ remove arg area
9992    b       common_resumeAfterGlueCall  @ continue to next instruction
9993    .endif
9994
9995
9996
9997/*
9998 * Common code for handling a return instruction.
9999 *
10000 * This does not return.
10001 */
10002common_returnFromMethod:
10003.LreturnNew:
10004    mov     r0, #kInterpEntryReturn
10005    mov     r9, #0
10006    bl      common_periodicChecks
10007
10008    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10009    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10010    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10011    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10012                                        @ r2<- method we're returning to
10013    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10014    cmp     r2, #0                      @ is this a break frame?
10015    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10016    mov     r1, #0                      @ "want switch" = false
10017    beq     common_gotoBail             @ break frame, bail out completely
10018
10019    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10020    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10021    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10022    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10023#if defined(WITH_JIT)
10024    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10025    GET_JIT_PROF_TABLE(r0)
10026    mov     rPC, r9                     @ publish new rPC
10027    str     r1, [rGLUE, #offGlue_methodClassDex]
10028    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10029    cmp     r10, #0                      @ caller is compiled code
10030    blxne   r10
10031    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10032    cmp     r0,#0
10033    bne     common_updateProfile
10034    GOTO_OPCODE(ip)                     @ jump to next instruction
10035#else
10036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10037    mov     rPC, r9                     @ publish new rPC
10038    str     r1, [rGLUE, #offGlue_methodClassDex]
10039    GOTO_OPCODE(ip)                     @ jump to next instruction
10040#endif
10041
10042    /*
10043     * Return handling, calls through "glue code".
10044     */
10045     .if    0
10046.LreturnOld:
10047    SAVE_PC_FP_TO_GLUE()                @ export state
10048    mov     r0, rGLUE                   @ arg to function
10049    bl      dvmMterp_returnFromMethod
10050    b       common_resumeAfterGlueCall
10051    .endif
10052
10053
10054/*
10055 * Somebody has thrown an exception.  Handle it.
10056 *
10057 * If the exception processing code returns to us (instead of falling
10058 * out of the interpreter), continue with whatever the next instruction
10059 * now happens to be.
10060 *
10061 * This does not return.
10062 */
10063     .global dvmMterpCommonExceptionThrown
10064dvmMterpCommonExceptionThrown:
10065common_exceptionThrown:
10066.LexceptionNew:
10067    mov     r0, #kInterpEntryThrow
10068    mov     r9, #0
10069    bl      common_periodicChecks
10070
10071    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10072    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10073    mov     r1, r10                     @ r1<- self
10074    mov     r0, r9                      @ r0<- exception
10075    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10076    mov     r3, #0                      @ r3<- NULL
10077    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10078
10079    /* set up args and a local for "&fp" */
10080    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10081    str     rFP, [sp, #-4]!             @ *--sp = fp
10082    mov     ip, sp                      @ ip<- &fp
10083    mov     r3, #0                      @ r3<- false
10084    str     ip, [sp, #-4]!              @ *--sp = &fp
10085    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10086    mov     r0, r10                     @ r0<- self
10087    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10088    mov     r2, r9                      @ r2<- exception
10089    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10090    mov     r1, r1, asr #1              @ r1<- offset in code units
10091
10092    /* call, r0 gets catchRelPc (a code-unit offset) */
10093    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10094
10095    /* fix earlier stack overflow if necessary; may trash rFP */
10096    ldrb    r1, [r10, #offThread_stackOverflowed]
10097    cmp     r1, #0                      @ did we overflow earlier?
10098    beq     1f                          @ no, skip ahead
10099    mov     rFP, r0                     @ save relPc result in rFP
10100    mov     r0, r10                     @ r0<- self
10101    mov     r1, r9                      @ r1<- exception
10102    bl      dvmCleanupStackOverflow     @ call(self)
10103    mov     r0, rFP                     @ restore result
101041:
10105
10106    /* update frame pointer and check result from dvmFindCatchBlock */
10107    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10108    cmp     r0, #0                      @ is catchRelPc < 0?
10109    add     sp, sp, #8                  @ restore stack
10110    bmi     .LnotCaughtLocally
10111
10112    /* adjust locals to match self->curFrame and updated PC */
10113    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10114    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10115    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10116    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10117    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10118    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10119    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10120    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10121
10122    /* release the tracked alloc on the exception */
10123    mov     r0, r9                      @ r0<- exception
10124    mov     r1, r10                     @ r1<- self
10125    bl      dvmReleaseTrackedAlloc      @ release the exception
10126
10127    /* restore the exception if the handler wants it */
10128    FETCH_INST()                        @ load rINST from rPC
10129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10130    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10131    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10132    GOTO_OPCODE(ip)                     @ jump to next instruction
10133
10134.LnotCaughtLocally: @ r9=exception, r10=self
10135    /* fix stack overflow if necessary */
10136    ldrb    r1, [r10, #offThread_stackOverflowed]
10137    cmp     r1, #0                      @ did we overflow earlier?
10138    movne   r0, r10                     @ if yes: r0<- self
10139    movne   r1, r9                      @ if yes: r1<- exception
10140    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10141
10142    @ may want to show "not caught locally" debug messages here
10143#if DVM_SHOW_EXCEPTION >= 2
10144    /* call __android_log_print(prio, tag, format, ...) */
10145    /* "Exception %s from %s:%d not caught locally" */
10146    @ dvmLineNumFromPC(method, pc - method->insns)
10147    ldr     r0, [rGLUE, #offGlue_method]
10148    ldr     r1, [r0, #offMethod_insns]
10149    sub     r1, rPC, r1
10150    asr     r1, r1, #1
10151    bl      dvmLineNumFromPC
10152    str     r0, [sp, #-4]!
10153    @ dvmGetMethodSourceFile(method)
10154    ldr     r0, [rGLUE, #offGlue_method]
10155    bl      dvmGetMethodSourceFile
10156    str     r0, [sp, #-4]!
10157    @ exception->clazz->descriptor
10158    ldr     r3, [r9, #offObject_clazz]
10159    ldr     r3, [r3, #offClassObject_descriptor]
10160    @
10161    ldr     r2, strExceptionNotCaughtLocally
10162    ldr     r1, strLogTag
10163    mov     r0, #3                      @ LOG_DEBUG
10164    bl      __android_log_print
10165#endif
10166    str     r9, [r10, #offThread_exception] @ restore exception
10167    mov     r0, r9                      @ r0<- exception
10168    mov     r1, r10                     @ r1<- self
10169    bl      dvmReleaseTrackedAlloc      @ release the exception
10170    mov     r1, #0                      @ "want switch" = false
10171    b       common_gotoBail             @ bail out
10172
10173
10174    /*
10175     * Exception handling, calls through "glue code".
10176     */
10177    .if     0
10178.LexceptionOld:
10179    SAVE_PC_FP_TO_GLUE()                @ export state
10180    mov     r0, rGLUE                   @ arg to function
10181    bl      dvmMterp_exceptionThrown
10182    b       common_resumeAfterGlueCall
10183    .endif
10184
10185
10186/*
10187 * After returning from a "glued" function, pull out the updated
10188 * values and start executing at the next instruction.
10189 */
10190common_resumeAfterGlueCall:
10191    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10192    FETCH_INST()                        @ load rINST from rPC
10193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10194    GOTO_OPCODE(ip)                     @ jump to next instruction
10195
10196/*
10197 * Invalid array index.
10198 */
10199common_errArrayIndex:
10200    EXPORT_PC()
10201    ldr     r0, strArrayIndexException
10202    mov     r1, #0
10203    bl      dvmThrowException
10204    b       common_exceptionThrown
10205
10206/*
10207 * Invalid array value.
10208 */
10209common_errArrayStore:
10210    EXPORT_PC()
10211    ldr     r0, strArrayStoreException
10212    mov     r1, #0
10213    bl      dvmThrowException
10214    b       common_exceptionThrown
10215
10216/*
10217 * Integer divide or mod by zero.
10218 */
10219common_errDivideByZero:
10220    EXPORT_PC()
10221    ldr     r0, strArithmeticException
10222    ldr     r1, strDivideByZero
10223    bl      dvmThrowException
10224    b       common_exceptionThrown
10225
10226/*
10227 * Attempt to allocate an array with a negative size.
10228 */
10229common_errNegativeArraySize:
10230    EXPORT_PC()
10231    ldr     r0, strNegativeArraySizeException
10232    mov     r1, #0
10233    bl      dvmThrowException
10234    b       common_exceptionThrown
10235
10236/*
10237 * Invocation of a non-existent method.
10238 */
10239common_errNoSuchMethod:
10240    EXPORT_PC()
10241    ldr     r0, strNoSuchMethodError
10242    mov     r1, #0
10243    bl      dvmThrowException
10244    b       common_exceptionThrown
10245
10246/*
10247 * We encountered a null object when we weren't expecting one.  We
10248 * export the PC, throw a NullPointerException, and goto the exception
10249 * processing code.
10250 */
10251common_errNullObject:
10252    EXPORT_PC()
10253    ldr     r0, strNullPointerException
10254    mov     r1, #0
10255    bl      dvmThrowException
10256    b       common_exceptionThrown
10257
10258/*
10259 * For debugging, cause an immediate fault.  The source address will
10260 * be in lr (use a bl instruction to jump here).
10261 */
10262common_abort:
10263    ldr     pc, .LdeadFood
10264.LdeadFood:
10265    .word   0xdeadf00d
10266
10267/*
10268 * Spit out a "we were here", preserving all registers.  (The attempt
10269 * to save ip won't work, but we need to save an even number of
10270 * registers for EABI 64-bit stack alignment.)
10271 */
10272    .macro  SQUEAK num
10273common_squeak\num:
10274    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10275    ldr     r0, strSqueak
10276    mov     r1, #\num
10277    bl      printf
10278    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10279    bx      lr
10280    .endm
10281
10282    SQUEAK  0
10283    SQUEAK  1
10284    SQUEAK  2
10285    SQUEAK  3
10286    SQUEAK  4
10287    SQUEAK  5
10288
10289/*
10290 * Spit out the number in r0, preserving registers.
10291 */
10292common_printNum:
10293    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10294    mov     r1, r0
10295    ldr     r0, strSqueak
10296    bl      printf
10297    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10298    bx      lr
10299
10300/*
10301 * Print a newline, preserving registers.
10302 */
10303common_printNewline:
10304    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10305    ldr     r0, strNewline
10306    bl      printf
10307    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10308    bx      lr
10309
10310    /*
10311     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10312     */
10313common_printHex:
10314    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10315    mov     r1, r0
10316    ldr     r0, strPrintHex
10317    bl      printf
10318    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10319    bx      lr
10320
10321/*
10322 * Print the 64-bit quantity in r0-r1, preserving registers.
10323 */
10324common_printLong:
10325    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10326    mov     r3, r1
10327    mov     r2, r0
10328    ldr     r0, strPrintLong
10329    bl      printf
10330    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10331    bx      lr
10332
10333/*
10334 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10335 */
10336common_printMethod:
10337    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10338    bl      dvmMterpPrintMethod
10339    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10340    bx      lr
10341
10342/*
10343 * Call a C helper function that dumps regs and possibly some
10344 * additional info.  Requires the C function to be compiled in.
10345 */
10346    .if     0
10347common_dumpRegs:
10348    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10349    bl      dvmMterpDumpArmRegs
10350    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10351    bx      lr
10352    .endif
10353
10354#if 0
10355/*
10356 * Experiment on VFP mode.
10357 *
10358 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10359 *
10360 * Updates the bits specified by "mask", setting them to the values in "val".
10361 */
10362setFPSCR:
10363    and     r0, r0, r1                  @ make sure no stray bits are set
10364    fmrx    r2, fpscr                   @ get VFP reg
10365    mvn     r1, r1                      @ bit-invert mask
10366    and     r2, r2, r1                  @ clear masked bits
10367    orr     r2, r2, r0                  @ set specified bits
10368    fmxr    fpscr, r2                   @ set VFP reg
10369    mov     r0, r2                      @ return new value
10370    bx      lr
10371
10372    .align  2
10373    .global dvmConfigureFP
10374    .type   dvmConfigureFP, %function
10375dvmConfigureFP:
10376    stmfd   sp!, {ip, lr}
10377    /* 0x03000000 sets DN/FZ */
10378    /* 0x00009f00 clears the six exception enable flags */
10379    bl      common_squeak0
10380    mov     r0, #0x03000000             @ r0<- 0x03000000
10381    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10382    bl      setFPSCR
10383    ldmfd   sp!, {ip, pc}
10384#endif
10385
10386
10387/*
10388 * String references, must be close to the code that uses them.
10389 */
10390    .align  2
10391strArithmeticException:
10392    .word   .LstrArithmeticException
10393strArrayIndexException:
10394    .word   .LstrArrayIndexException
10395strArrayStoreException:
10396    .word   .LstrArrayStoreException
10397strDivideByZero:
10398    .word   .LstrDivideByZero
10399strNegativeArraySizeException:
10400    .word   .LstrNegativeArraySizeException
10401strNoSuchMethodError:
10402    .word   .LstrNoSuchMethodError
10403strNullPointerException:
10404    .word   .LstrNullPointerException
10405
10406strLogTag:
10407    .word   .LstrLogTag
10408strExceptionNotCaughtLocally:
10409    .word   .LstrExceptionNotCaughtLocally
10410
10411strNewline:
10412    .word   .LstrNewline
10413strSqueak:
10414    .word   .LstrSqueak
10415strPrintHex:
10416    .word   .LstrPrintHex
10417strPrintLong:
10418    .word   .LstrPrintLong
10419
10420/*
10421 * Zero-terminated ASCII string data.
10422 *
10423 * On ARM we have two choices: do like gcc does, and LDR from a .word
10424 * with the address, or use an ADR pseudo-op to get the address
10425 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10426 * PC-relative addressing mode and hence has a limited range, which
10427 * makes it not work well with mergeable string sections.
10428 */
10429    .section .rodata.str1.4,"aMS",%progbits,1
10430
10431.LstrBadEntryPoint:
10432    .asciz  "Bad entry point %d\n"
10433.LstrArithmeticException:
10434    .asciz  "Ljava/lang/ArithmeticException;"
10435.LstrArrayIndexException:
10436    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10437.LstrArrayStoreException:
10438    .asciz  "Ljava/lang/ArrayStoreException;"
10439.LstrClassCastException:
10440    .asciz  "Ljava/lang/ClassCastException;"
10441.LstrDivideByZero:
10442    .asciz  "divide by zero"
10443.LstrFilledNewArrayNotImpl:
10444    .asciz  "filled-new-array only implemented for objects and 'int'"
10445.LstrInternalError:
10446    .asciz  "Ljava/lang/InternalError;"
10447.LstrInstantiationError:
10448    .asciz  "Ljava/lang/InstantiationError;"
10449.LstrNegativeArraySizeException:
10450    .asciz  "Ljava/lang/NegativeArraySizeException;"
10451.LstrNoSuchMethodError:
10452    .asciz  "Ljava/lang/NoSuchMethodError;"
10453.LstrNullPointerException:
10454    .asciz  "Ljava/lang/NullPointerException;"
10455
10456.LstrLogTag:
10457    .asciz  "mterp"
10458.LstrExceptionNotCaughtLocally:
10459    .asciz  "Exception %s from %s:%d not caught locally\n"
10460
10461.LstrNewline:
10462    .asciz  "\n"
10463.LstrSqueak:
10464    .asciz  "<%d>"
10465.LstrPrintHex:
10466    .asciz  "<0x%x>"
10467.LstrPrintLong:
10468    .asciz  "<%lld>"
10469
10470
10471