InterpAsm-armv7-a.S revision 0890e5bf0b2a502ca1030e9773fabc16ef1b5981
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/*
25 * ARMv5 definitions and declarations.
26 */
27
28/*
29ARM EABI general notes:
30
31r0-r3 hold first 4 args to a method; they are not preserved across method calls
32r4-r8 are available for general use
33r9 is given special treatment in some situations, but not for us
34r10 (sl) seems to be generally available
35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
36r12 (ip) is scratch -- not preserved across method calls
37r13 (sp) should be managed carefully in case a signal arrives
38r14 (lr) must be preserved
39r15 (pc) can be tinkered with directly
40
41r0 holds returns of <= 4 bytes
42r0-r1 hold returns of 8 bytes, low word in r0
43
44Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
46s0-s15 (d0-d7, q0-a3) do not need to be.
47
48Stack is "full descending".  Only the arguments that don't fit in the first 4
49registers are placed on the stack.  "sp" points at the first stacked argument
50(i.e. the 5th arg).
51
52VFP: single-precision results in s0, double-precision results in d0.
53
54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5564-bit quantities (long long, double) must be 64-bit aligned.
56*/
57
58/*
59Mterp and ARM notes:
60
61The following registers have fixed assignments:
62
63  reg nick      purpose
64  r4  rPC       interpreted program counter, used for fetching instructions
65  r5  rFP       interpreted frame pointer, used for accessing locals and args
66  r6  rGLUE     MterpGlue pointer
67  r7  rINST     first 16-bit code unit of current instruction
68  r8  rIBASE    interpreted instruction base pointer, used for computed goto
69
70Macros are provided for common operations.  Each macro MUST emit only
71one instruction to make instruction-counting easier.  They MUST NOT alter
72unspecified registers or condition codes.
73*/
74
75/* single-purpose registers, given names for clarity */
76#define rPC     r4
77#define rFP     r5
78#define rGLUE   r6
79#define rINST   r7
80#define rIBASE  r8
81
82/* save/restore the PC and/or FP from the glue struct */
83#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
84#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
85#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
86#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
87#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
88#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
89
90/*
91 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
92 * be done *before* something calls dvmThrowException.
93 *
94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96 *
97 * It's okay to do this more than once.
98 */
99#define EXPORT_PC() \
100    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
101
102/*
103 * Given a frame pointer, find the stack save area.
104 *
105 * In C this is "((StackSaveArea*)(_fp) -1)".
106 */
107#define SAVEAREA_FROM_FP(_reg, _fpreg) \
108    sub     _reg, _fpreg, #sizeofStackSaveArea
109
110/*
111 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
112 */
113#define FETCH_INST()            ldrh    rINST, [rPC]
114
115/*
116 * Fetch the next instruction from the specified offset.  Advances rPC
117 * to point to the next instruction.  "_count" is in 16-bit code units.
118 *
119 * Because of the limited size of immediate constants on ARM, this is only
120 * suitable for small forward movements (i.e. don't try to implement "goto"
121 * with this).
122 *
123 * This must come AFTER anything that can throw an exception, or the
124 * exception catch may miss.  (This also implies that it must come after
125 * EXPORT_PC().)
126 */
127#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
128
129/*
130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
131 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132 */
133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
134        ldrh    _dreg, [_sreg, #(_count*2)]!
135
136/*
137 * Fetch the next instruction from an offset specified by _reg.  Updates
138 * rPC to point to the next instruction.  "_reg" must specify the distance
139 * in bytes, *not* 16-bit code units, and may be a signed value.
140 *
141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
142 * bits that hold the shift distance are used for the half/byte/sign flags.
143 * In some cases we can pre-double _reg for free, so we require a byte offset
144 * here.
145 */
146#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
147
148/*
149 * Fetch a half-word code unit from an offset past the current PC.  The
150 * "_count" value is in 16-bit code units.  Does not advance rPC.
151 *
152 * The "_S" variant works the same but treats the value as signed.
153 */
154#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
155#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
156
157/*
158 * Fetch one byte from an offset past the current PC.  Pass in the same
159 * "_count" as you would for FETCH, and an additional 0/1 indicating which
160 * byte of the halfword you want (lo/hi).
161 */
162#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
163
164/*
165 * Put the instruction's opcode field into the specified register.
166 */
167#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
168
169/*
170 * Put the prefetched instruction's opcode field into the specified register.
171 */
172#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
173
174/*
175 * Begin executing the opcode in _reg.  Because this only jumps within the
176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177 */
178#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
180#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
181
182/*
183 * Get/set the 32-bit value from a Dalvik register.
184 */
185#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
186#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
187
188#if defined(WITH_JIT)
189#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
191#endif
192
193/*
194 * Convert a virtual register index into an address.
195 */
196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
197        add     _reg, rFP, _vreg, lsl #2
198
199/*
200 * This is a #include, not a %include, because we want the C pre-processor
201 * to expand the macros into assembler assignment statements.
202 */
203#include "../common/asm-constants.h"
204
205#if defined(WITH_JIT)
206#include "../common/jit-config.h"
207#endif
208
209/* File: armv7-a/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216/*
217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
218 * one-way branch.
219 *
220 * May modify IP.  Does not modify LR.
221 */
222.macro  LDR_PC source
223    ldr     pc, \source
224.endm
225
226/*
227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
228 * Jump to subroutine.
229 *
230 * May modify IP and LR.
231 */
232.macro  LDR_PC_LR source
233    mov     lr, pc
234    ldr     pc, \source
235.endm
236
237/*
238 * Macro for "LDMFD SP!, {...regs...,PC}".
239 *
240 * May modify IP and LR.
241 */
242.macro  LDMFD_PC regs
243    ldmfd   sp!, {\regs,pc}
244.endm
245
246#if !defined(ANDROID_SMP)
247# error "Must define ANDROID_SMP"
248#endif
249
250/*
251 * Macro for data memory barrier; not meaningful pre-ARMv6K.
252 * If the argument is nonzero, emit barrier; otherwise, emit nothing.
253 */
254.macro  SMP_DMB
255#if ANDROID_SMP != 0
256    dmb
257#else
258    /* not SMP */
259#endif
260.endm
261
262/* File: armv5te/entry.S */
263/*
264 * Copyright (C) 2008 The Android Open Source Project
265 *
266 * Licensed under the Apache License, Version 2.0 (the "License");
267 * you may not use this file except in compliance with the License.
268 * You may obtain a copy of the License at
269 *
270 *      http://www.apache.org/licenses/LICENSE-2.0
271 *
272 * Unless required by applicable law or agreed to in writing, software
273 * distributed under the License is distributed on an "AS IS" BASIS,
274 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
275 * See the License for the specific language governing permissions and
276 * limitations under the License.
277 */
278/*
279 * Interpreter entry point.
280 */
281
282/*
283 * We don't have formal stack frames, so gdb scans upward in the code
284 * to find the start of the function (a label with the %function type),
285 * and then looks at the next few instructions to figure out what
286 * got pushed onto the stack.  From this it figures out how to restore
287 * the registers, including PC, for the previous stack frame.  If gdb
288 * sees a non-function label, it stops scanning, so either we need to
289 * have nothing but assembler-local labels between the entry point and
290 * the break, or we need to fake it out.
291 *
292 * When this is defined, we add some stuff to make gdb less confused.
293 */
294#define ASSIST_DEBUGGER 1
295
296    .text
297    .align  2
298    .global dvmMterpStdRun
299    .type   dvmMterpStdRun, %function
300
301/*
302 * On entry:
303 *  r0  MterpGlue* glue
304 *
305 * This function returns a boolean "changeInterp" value.  The return comes
306 * via a call to dvmMterpStdBail().
307 */
308dvmMterpStdRun:
309#define MTERP_ENTRY1 \
310    .save {r4-r10,fp,lr}; \
311    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
312#define MTERP_ENTRY2 \
313    .pad    #4; \
314    sub     sp, sp, #4                  @ align 64
315
316    .fnstart
317    MTERP_ENTRY1
318    MTERP_ENTRY2
319
320    /* save stack pointer, add magic word for debuggerd */
321    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
322
323    /* set up "named" registers, figure out entry point */
324    mov     rGLUE, r0                   @ set rGLUE
325    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
326    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
327    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
328    cmp     r1, #kInterpEntryInstr      @ usual case?
329    bne     .Lnot_instr                 @ no, handle it
330
331#if defined(WITH_JIT)
332.LentryInstr:
333    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
334    /* Entry is always a possible trace start */
335    GET_JIT_PROF_TABLE(r0)
336    FETCH_INST()
337    mov    r1, #0                       @ prepare the value for the new state
338    str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
339    cmp    r0,#0
340    bne    common_updateProfile
341    GET_INST_OPCODE(ip)
342    GOTO_OPCODE(ip)
343#else
344    /* start executing the instruction at rPC */
345    FETCH_INST()                        @ load rINST from rPC
346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
347    GOTO_OPCODE(ip)                     @ jump to next instruction
348#endif
349
350.Lnot_instr:
351    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
352    beq     common_returnFromMethod
353
354.Lnot_return:
355    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
356    beq     common_exceptionThrown
357
358#if defined(WITH_JIT)
359.Lnot_throw:
360    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
361    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
362    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
363    bne     .Lbad_arg
364    cmp     rPC,r2
365    bne     .LentryInstr                @ must have branched, don't resume
366#if defined(WITH_SELF_VERIFICATION)
367    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
368    b       jitSVShadowRunStart         @ re-enter the translation after the
369                                        @ single-stepped instruction
370    @noreturn
371#endif
372    mov     r1, #kInterpEntryInstr
373    str     r1, [rGLUE, #offGlue_entryPoint]
374    bx      r10                         @ re-enter the translation
375#endif
376
377.Lbad_arg:
378    ldr     r0, strBadEntryPoint
379    @ r1 holds value of entryPoint
380    bl      printf
381    bl      dvmAbort
382    .fnend
383
384
385    .global dvmMterpStdBail
386    .type   dvmMterpStdBail, %function
387
388/*
389 * Restore the stack pointer and PC from the save point established on entry.
390 * This is essentially the same as a longjmp, but should be cheaper.  The
391 * last instruction causes us to return to whoever called dvmMterpStdRun.
392 *
393 * We pushed some registers on the stack in dvmMterpStdRun, then saved
394 * SP and LR.  Here we restore SP, restore the registers, and then restore
395 * LR to PC.
396 *
397 * On entry:
398 *  r0  MterpGlue* glue
399 *  r1  bool changeInterp
400 */
401dvmMterpStdBail:
402    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
403    mov     r0, r1                          @ return the changeInterp value
404    add     sp, sp, #4                      @ un-align 64
405    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
406
407
408/*
409 * String references.
410 */
411strBadEntryPoint:
412    .word   .LstrBadEntryPoint
413
414
415    .global dvmAsmInstructionStart
416    .type   dvmAsmInstructionStart, %function
417dvmAsmInstructionStart = .L_OP_NOP
418    .text
419
420/* ------------------------------ */
421    .balign 64
422.L_OP_NOP: /* 0x00 */
423/* File: armv5te/OP_NOP.S */
424    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
425    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
426    GOTO_OPCODE(ip)                     @ execute it
427
428#ifdef ASSIST_DEBUGGER
429    /* insert fake function header to help gdb find the stack frame */
430    .type   dalvik_inst, %function
431dalvik_inst:
432    .fnstart
433    MTERP_ENTRY1
434    MTERP_ENTRY2
435    .fnend
436#endif
437
438/* ------------------------------ */
439    .balign 64
440.L_OP_MOVE: /* 0x01 */
441/* File: armv6t2/OP_MOVE.S */
442    /* for move, move-object, long-to-int */
443    /* op vA, vB */
444    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
445    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
446    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
447    GET_VREG(r2, r1)                    @ r2<- fp[B]
448    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
449    SET_VREG(r2, r0)                    @ fp[A]<- r2
450    GOTO_OPCODE(ip)                     @ execute next instruction
451
452/* ------------------------------ */
453    .balign 64
454.L_OP_MOVE_FROM16: /* 0x02 */
455/* File: armv5te/OP_MOVE_FROM16.S */
456    /* for: move/from16, move-object/from16 */
457    /* op vAA, vBBBB */
458    FETCH(r1, 1)                        @ r1<- BBBB
459    mov     r0, rINST, lsr #8           @ r0<- AA
460    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
461    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
462    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
463    SET_VREG(r2, r0)                    @ fp[AA]<- r2
464    GOTO_OPCODE(ip)                     @ jump to next instruction
465
466/* ------------------------------ */
467    .balign 64
468.L_OP_MOVE_16: /* 0x03 */
469/* File: armv5te/OP_MOVE_16.S */
470    /* for: move/16, move-object/16 */
471    /* op vAAAA, vBBBB */
472    FETCH(r1, 2)                        @ r1<- BBBB
473    FETCH(r0, 1)                        @ r0<- AAAA
474    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
475    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
476    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
477    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
478    GOTO_OPCODE(ip)                     @ jump to next instruction
479
480/* ------------------------------ */
481    .balign 64
482.L_OP_MOVE_WIDE: /* 0x04 */
483/* File: armv6t2/OP_MOVE_WIDE.S */
484    /* move-wide vA, vB */
485    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
486    mov     r3, rINST, lsr #12          @ r3<- B
487    ubfx    r2, rINST, #8, #4           @ r2<- A
488    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
489    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
490    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
491    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
492    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
493    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
494    GOTO_OPCODE(ip)                     @ jump to next instruction
495
496/* ------------------------------ */
497    .balign 64
498.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
499/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
500    /* move-wide/from16 vAA, vBBBB */
501    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
502    FETCH(r3, 1)                        @ r3<- BBBB
503    mov     r2, rINST, lsr #8           @ r2<- AA
504    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
505    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
506    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
507    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
509    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
510    GOTO_OPCODE(ip)                     @ jump to next instruction
511
512/* ------------------------------ */
513    .balign 64
514.L_OP_MOVE_WIDE_16: /* 0x06 */
515/* File: armv5te/OP_MOVE_WIDE_16.S */
516    /* move-wide/16 vAAAA, vBBBB */
517    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
518    FETCH(r3, 2)                        @ r3<- BBBB
519    FETCH(r2, 1)                        @ r2<- AAAA
520    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
521    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
522    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
523    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
524    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
525    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
526    GOTO_OPCODE(ip)                     @ jump to next instruction
527
528/* ------------------------------ */
529    .balign 64
530.L_OP_MOVE_OBJECT: /* 0x07 */
531/* File: armv5te/OP_MOVE_OBJECT.S */
532/* File: armv5te/OP_MOVE.S */
533    /* for move, move-object, long-to-int */
534    /* op vA, vB */
535    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
536    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
537    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
538    GET_VREG(r2, r1)                    @ r2<- fp[B]
539    and     r0, r0, #15
540    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
541    SET_VREG(r2, r0)                    @ fp[A]<- r2
542    GOTO_OPCODE(ip)                     @ execute next instruction
543
544
545/* ------------------------------ */
546    .balign 64
547.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
548/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
549/* File: armv5te/OP_MOVE_FROM16.S */
550    /* for: move/from16, move-object/from16 */
551    /* op vAA, vBBBB */
552    FETCH(r1, 1)                        @ r1<- BBBB
553    mov     r0, rINST, lsr #8           @ r0<- AA
554    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
555    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
556    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
557    SET_VREG(r2, r0)                    @ fp[AA]<- r2
558    GOTO_OPCODE(ip)                     @ jump to next instruction
559
560
561/* ------------------------------ */
562    .balign 64
563.L_OP_MOVE_OBJECT_16: /* 0x09 */
564/* File: armv5te/OP_MOVE_OBJECT_16.S */
565/* File: armv5te/OP_MOVE_16.S */
566    /* for: move/16, move-object/16 */
567    /* op vAAAA, vBBBB */
568    FETCH(r1, 2)                        @ r1<- BBBB
569    FETCH(r0, 1)                        @ r0<- AAAA
570    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
571    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
572    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
573    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
574    GOTO_OPCODE(ip)                     @ jump to next instruction
575
576
577/* ------------------------------ */
578    .balign 64
579.L_OP_MOVE_RESULT: /* 0x0a */
580/* File: armv5te/OP_MOVE_RESULT.S */
581    /* for: move-result, move-result-object */
582    /* op vAA */
583    mov     r2, rINST, lsr #8           @ r2<- AA
584    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
585    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
587    SET_VREG(r0, r2)                    @ fp[AA]<- r0
588    GOTO_OPCODE(ip)                     @ jump to next instruction
589
590/* ------------------------------ */
591    .balign 64
592.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
593/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
594    /* move-result-wide vAA */
595    mov     r2, rINST, lsr #8           @ r2<- AA
596    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
597    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
598    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
599    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
600    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
601    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
602    GOTO_OPCODE(ip)                     @ jump to next instruction
603
604/* ------------------------------ */
605    .balign 64
606.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
607/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
608/* File: armv5te/OP_MOVE_RESULT.S */
609    /* for: move-result, move-result-object */
610    /* op vAA */
611    mov     r2, rINST, lsr #8           @ r2<- AA
612    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
613    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
614    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
615    SET_VREG(r0, r2)                    @ fp[AA]<- r0
616    GOTO_OPCODE(ip)                     @ jump to next instruction
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    .balign 64
636.L_OP_RETURN_VOID: /* 0x0e */
637/* File: armv5te/OP_RETURN_VOID.S */
638    b       common_returnFromMethod
639
640/* ------------------------------ */
641    .balign 64
642.L_OP_RETURN: /* 0x0f */
643/* File: armv5te/OP_RETURN.S */
644    /*
645     * Return a 32-bit value.  Copies the return value into the "glue"
646     * structure, then jumps to the return handler.
647     *
648     * for: return, return-object
649     */
650    /* op vAA */
651    mov     r2, rINST, lsr #8           @ r2<- AA
652    GET_VREG(r0, r2)                    @ r0<- vAA
653    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
654    b       common_returnFromMethod
655
656/* ------------------------------ */
657    .balign 64
658.L_OP_RETURN_WIDE: /* 0x10 */
659/* File: armv5te/OP_RETURN_WIDE.S */
660    /*
661     * Return a 64-bit value.  Copies the return value into the "glue"
662     * structure, then jumps to the return handler.
663     */
664    /* return-wide vAA */
665    mov     r2, rINST, lsr #8           @ r2<- AA
666    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
667    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
668    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
669    stmia   r3, {r0-r1}                 @ retval<- r0/r1
670    b       common_returnFromMethod
671
672/* ------------------------------ */
673    .balign 64
674.L_OP_RETURN_OBJECT: /* 0x11 */
675/* File: armv5te/OP_RETURN_OBJECT.S */
676/* File: armv5te/OP_RETURN.S */
677    /*
678     * Return a 32-bit value.  Copies the return value into the "glue"
679     * structure, then jumps to the return handler.
680     *
681     * for: return, return-object
682     */
683    /* op vAA */
684    mov     r2, rINST, lsr #8           @ r2<- AA
685    GET_VREG(r0, r2)                    @ r0<- vAA
686    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
687    b       common_returnFromMethod
688
689
690/* ------------------------------ */
691    .balign 64
692.L_OP_CONST_4: /* 0x12 */
693/* File: armv6t2/OP_CONST_4.S */
694    /* const/4 vA, #+B */
695    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
696    ubfx    r0, rINST, #8, #4           @ r0<- A
697    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
698    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
699    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
700    SET_VREG(r1, r0)                    @ fp[A]<- r1
701    GOTO_OPCODE(ip)                     @ execute next instruction
702
703/* ------------------------------ */
704    .balign 64
705.L_OP_CONST_16: /* 0x13 */
706/* File: armv5te/OP_CONST_16.S */
707    /* const/16 vAA, #+BBBB */
708    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
709    mov     r3, rINST, lsr #8           @ r3<- AA
710    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
711    SET_VREG(r0, r3)                    @ vAA<- r0
712    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
713    GOTO_OPCODE(ip)                     @ jump to next instruction
714
715/* ------------------------------ */
716    .balign 64
717.L_OP_CONST: /* 0x14 */
718/* File: armv5te/OP_CONST.S */
719    /* const vAA, #+BBBBbbbb */
720    mov     r3, rINST, lsr #8           @ r3<- AA
721    FETCH(r0, 1)                        @ r0<- bbbb (low)
722    FETCH(r1, 2)                        @ r1<- BBBB (high)
723    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
724    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
726    SET_VREG(r0, r3)                    @ vAA<- r0
727    GOTO_OPCODE(ip)                     @ jump to next instruction
728
729/* ------------------------------ */
730    .balign 64
731.L_OP_CONST_HIGH16: /* 0x15 */
732/* File: armv5te/OP_CONST_HIGH16.S */
733    /* const/high16 vAA, #+BBBB0000 */
734    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
735    mov     r3, rINST, lsr #8           @ r3<- AA
736    mov     r0, r0, lsl #16             @ r0<- BBBB0000
737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
738    SET_VREG(r0, r3)                    @ vAA<- r0
739    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
740    GOTO_OPCODE(ip)                     @ jump to next instruction
741
742/* ------------------------------ */
743    .balign 64
744.L_OP_CONST_WIDE_16: /* 0x16 */
745/* File: armv5te/OP_CONST_WIDE_16.S */
746    /* const-wide/16 vAA, #+BBBB */
747    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
748    mov     r3, rINST, lsr #8           @ r3<- AA
749    mov     r1, r0, asr #31             @ r1<- ssssssss
750    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
751    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
753    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
754    GOTO_OPCODE(ip)                     @ jump to next instruction
755
756/* ------------------------------ */
757    .balign 64
758.L_OP_CONST_WIDE_32: /* 0x17 */
759/* File: armv5te/OP_CONST_WIDE_32.S */
760    /* const-wide/32 vAA, #+BBBBbbbb */
761    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
762    mov     r3, rINST, lsr #8           @ r3<- AA
763    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
764    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
765    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
766    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
767    mov     r1, r0, asr #31             @ r1<- ssssssss
768    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
769    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
770    GOTO_OPCODE(ip)                     @ jump to next instruction
771
772/* ------------------------------ */
773    .balign 64
774.L_OP_CONST_WIDE: /* 0x18 */
775/* File: armv5te/OP_CONST_WIDE.S */
776    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
777    FETCH(r0, 1)                        @ r0<- bbbb (low)
778    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
779    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
780    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
781    FETCH(r3, 4)                        @ r3<- HHHH (high)
782    mov     r9, rINST, lsr #8           @ r9<- AA
783    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
784    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
785    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
786    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
787    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
788    GOTO_OPCODE(ip)                     @ jump to next instruction
789
790/* ------------------------------ */
791    .balign 64
792.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
793/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
794    /* const-wide/high16 vAA, #+BBBB000000000000 */
795    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
796    mov     r3, rINST, lsr #8           @ r3<- AA
797    mov     r0, #0                      @ r0<- 00000000
798    mov     r1, r1, lsl #16             @ r1<- BBBB0000
799    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
800    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
802    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
803    GOTO_OPCODE(ip)                     @ jump to next instruction
804
805/* ------------------------------ */
806    .balign 64
807.L_OP_CONST_STRING: /* 0x1a */
808/* File: armv5te/OP_CONST_STRING.S */
809    /* const/string vAA, String@BBBB */
810    FETCH(r1, 1)                        @ r1<- BBBB
811    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
812    mov     r9, rINST, lsr #8           @ r9<- AA
813    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
814    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
815    cmp     r0, #0                      @ not yet resolved?
816    beq     .LOP_CONST_STRING_resolve
817    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
818    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
819    SET_VREG(r0, r9)                    @ vAA<- r0
820    GOTO_OPCODE(ip)                     @ jump to next instruction
821
822/* ------------------------------ */
823    .balign 64
824.L_OP_CONST_STRING_JUMBO: /* 0x1b */
825/* File: armv5te/OP_CONST_STRING_JUMBO.S */
826    /* const/string vAA, String@BBBBBBBB */
827    FETCH(r0, 1)                        @ r0<- bbbb (low)
828    FETCH(r1, 2)                        @ r1<- BBBB (high)
829    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
830    mov     r9, rINST, lsr #8           @ r9<- AA
831    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
832    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
833    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
834    cmp     r0, #0
835    beq     .LOP_CONST_STRING_JUMBO_resolve
836    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
837    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
838    SET_VREG(r0, r9)                    @ vAA<- r0
839    GOTO_OPCODE(ip)                     @ jump to next instruction
840
841/* ------------------------------ */
842    .balign 64
843.L_OP_CONST_CLASS: /* 0x1c */
844/* File: armv5te/OP_CONST_CLASS.S */
845    /* const/class vAA, Class@BBBB */
846    FETCH(r1, 1)                        @ r1<- BBBB
847    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
848    mov     r9, rINST, lsr #8           @ r9<- AA
849    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
850    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
851    cmp     r0, #0                      @ not yet resolved?
852    beq     .LOP_CONST_CLASS_resolve
853    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
854    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
855    SET_VREG(r0, r9)                    @ vAA<- r0
856    GOTO_OPCODE(ip)                     @ jump to next instruction
857
858/* ------------------------------ */
859    .balign 64
860.L_OP_MONITOR_ENTER: /* 0x1d */
861/* File: armv5te/OP_MONITOR_ENTER.S */
862    /*
863     * Synchronize on an object.
864     */
865    /* monitor-enter vAA */
866    mov     r2, rINST, lsr #8           @ r2<- AA
867    GET_VREG(r1, r2)                    @ r1<- vAA (object)
868    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
869    cmp     r1, #0                      @ null object?
870    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
871    beq     common_errNullObject        @ null object, throw an exception
872    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
873    bl      dvmLockObject               @ call(self, obj)
874#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
875    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
876    ldr     r1, [r0, #offThread_exception] @ check for exception
877    cmp     r1, #0
878    bne     common_exceptionThrown      @ exception raised, bail out
879#endif
880    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
881    GOTO_OPCODE(ip)                     @ jump to next instruction
882
883/* ------------------------------ */
884    .balign 64
885.L_OP_MONITOR_EXIT: /* 0x1e */
886/* File: armv5te/OP_MONITOR_EXIT.S */
887    /*
888     * Unlock an object.
889     *
890     * Exceptions that occur when unlocking a monitor need to appear as
891     * if they happened at the following instruction.  See the Dalvik
892     * instruction spec.
893     */
894    /* monitor-exit vAA */
895    mov     r2, rINST, lsr #8           @ r2<- AA
896    EXPORT_PC()                         @ before fetch: export the PC
897    GET_VREG(r1, r2)                    @ r1<- vAA (object)
898    cmp     r1, #0                      @ null object?
899    beq     1f                          @ yes
900    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
901    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
902    cmp     r0, #0                      @ failed?
903    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
904    beq     common_exceptionThrown      @ yes, exception is pending
905    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
906    GOTO_OPCODE(ip)                     @ jump to next instruction
9071:
908    FETCH_ADVANCE_INST(1)               @ advance before throw
909    b      common_errNullObject
910
911/* ------------------------------ */
912    .balign 64
913.L_OP_CHECK_CAST: /* 0x1f */
914/* File: armv5te/OP_CHECK_CAST.S */
915    /*
916     * Check to see if a cast from one class to another is allowed.
917     */
918    /* check-cast vAA, class@BBBB */
919    mov     r3, rINST, lsr #8           @ r3<- AA
920    FETCH(r2, 1)                        @ r2<- BBBB
921    GET_VREG(r9, r3)                    @ r9<- object
922    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
923    cmp     r9, #0                      @ is object null?
924    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
925    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
926    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
927    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
928    cmp     r1, #0                      @ have we resolved this before?
929    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
930.LOP_CHECK_CAST_resolved:
931    cmp     r0, r1                      @ same class (trivial success)?
932    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
933.LOP_CHECK_CAST_okay:
934    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
935    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
936    GOTO_OPCODE(ip)                     @ jump to next instruction
937
938/* ------------------------------ */
939    .balign 64
940.L_OP_INSTANCE_OF: /* 0x20 */
941/* File: armv5te/OP_INSTANCE_OF.S */
942    /*
943     * Check to see if an object reference is an instance of a class.
944     *
945     * Most common situation is a non-null object, being compared against
946     * an already-resolved class.
947     */
948    /* instance-of vA, vB, class@CCCC */
949    mov     r3, rINST, lsr #12          @ r3<- B
950    mov     r9, rINST, lsr #8           @ r9<- A+
951    GET_VREG(r0, r3)                    @ r0<- vB (object)
952    and     r9, r9, #15                 @ r9<- A
953    cmp     r0, #0                      @ is object null?
954    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
955    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
956    FETCH(r3, 1)                        @ r3<- CCCC
957    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
958    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
959    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
960    cmp     r1, #0                      @ have we resolved this before?
961    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
962.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
963    cmp     r0, r1                      @ same class (trivial success)?
964    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
965    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
966
967/* ------------------------------ */
968    .balign 64
969.L_OP_ARRAY_LENGTH: /* 0x21 */
970/* File: armv6t2/OP_ARRAY_LENGTH.S */
971    /*
972     * Return the length of an array.
973     */
974    mov     r1, rINST, lsr #12          @ r1<- B
975    ubfx    r2, rINST, #8, #4           @ r2<- A
976    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
977    cmp     r0, #0                      @ is object null?
978    beq     common_errNullObject        @ yup, fail
979    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
980    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
981    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
982    SET_VREG(r3, r2)                    @ vB<- length
983    GOTO_OPCODE(ip)                     @ jump to next instruction
984
985/* ------------------------------ */
986    .balign 64
987.L_OP_NEW_INSTANCE: /* 0x22 */
988/* File: armv5te/OP_NEW_INSTANCE.S */
989    /*
990     * Create a new instance of a class.
991     */
992    /* new-instance vAA, class@BBBB */
993    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
994    FETCH(r1, 1)                        @ r1<- BBBB
995    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
996    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
997    EXPORT_PC()                         @ req'd for init, resolve, alloc
998    cmp     r0, #0                      @ already resolved?
999    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1000.LOP_NEW_INSTANCE_resolved:   @ r0=class
1001    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1002    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1003    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1004.LOP_NEW_INSTANCE_initialized: @ r0=class
1005    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1006    bl      dvmAllocObject              @ r0<- new object
1007    b       .LOP_NEW_INSTANCE_finish          @ continue
1008
1009/* ------------------------------ */
1010    .balign 64
1011.L_OP_NEW_ARRAY: /* 0x23 */
1012/* File: armv5te/OP_NEW_ARRAY.S */
1013    /*
1014     * Allocate an array of objects, specified with the array class
1015     * and a count.
1016     *
1017     * The verifier guarantees that this is an array class, so we don't
1018     * check for it here.
1019     */
1020    /* new-array vA, vB, class@CCCC */
1021    mov     r0, rINST, lsr #12          @ r0<- B
1022    FETCH(r2, 1)                        @ r2<- CCCC
1023    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1024    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1025    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1026    cmp     r1, #0                      @ check length
1027    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1028    bmi     common_errNegativeArraySize @ negative length, bail
1029    cmp     r0, #0                      @ already resolved?
1030    EXPORT_PC()                         @ req'd for resolve, alloc
1031    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1032    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1033
1034/* ------------------------------ */
1035    .balign 64
1036.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1037/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1038    /*
1039     * Create a new array with elements filled from registers.
1040     *
1041     * for: filled-new-array, filled-new-array/range
1042     */
1043    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1044    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1045    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1046    FETCH(r1, 1)                        @ r1<- BBBB
1047    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1048    EXPORT_PC()                         @ need for resolve and alloc
1049    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1050    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1051    cmp     r0, #0                      @ already resolved?
1052    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10538:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1054    mov     r2, #0                      @ r2<- false
1055    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1056    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1057    cmp     r0, #0                      @ got null?
1058    beq     common_exceptionThrown      @ yes, handle exception
1059    b       .LOP_FILLED_NEW_ARRAY_continue
1060
1061/* ------------------------------ */
1062    .balign 64
1063.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1064/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1065/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1066    /*
1067     * Create a new array with elements filled from registers.
1068     *
1069     * for: filled-new-array, filled-new-array/range
1070     */
1071    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1072    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1073    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1074    FETCH(r1, 1)                        @ r1<- BBBB
1075    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1076    EXPORT_PC()                         @ need for resolve and alloc
1077    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1078    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1079    cmp     r0, #0                      @ already resolved?
1080    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10818:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1082    mov     r2, #0                      @ r2<- false
1083    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1084    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1085    cmp     r0, #0                      @ got null?
1086    beq     common_exceptionThrown      @ yes, handle exception
1087    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1088
1089
1090/* ------------------------------ */
1091    .balign 64
1092.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1093/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1094    /* fill-array-data vAA, +BBBBBBBB */
1095    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1096    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1097    mov     r3, rINST, lsr #8           @ r3<- AA
1098    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1099    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1100    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1101    EXPORT_PC();
1102    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1103    cmp     r0, #0                      @ 0 means an exception is thrown
1104    beq     common_exceptionThrown      @ has exception
1105    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1106    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1107    GOTO_OPCODE(ip)                     @ jump to next instruction
1108
1109/* ------------------------------ */
1110    .balign 64
1111.L_OP_THROW: /* 0x27 */
1112/* File: armv5te/OP_THROW.S */
1113    /*
1114     * Throw an exception object in the current thread.
1115     */
1116    /* throw vAA */
1117    mov     r2, rINST, lsr #8           @ r2<- AA
1118    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1119    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1120    EXPORT_PC()                         @ exception handler can throw
1121    cmp     r1, #0                      @ null object?
1122    beq     common_errNullObject        @ yes, throw an NPE instead
1123    @ bypass dvmSetException, just store it
1124    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1125    b       common_exceptionThrown
1126
1127/* ------------------------------ */
1128    .balign 64
1129.L_OP_GOTO: /* 0x28 */
1130/* File: armv5te/OP_GOTO.S */
1131    /*
1132     * Unconditional branch, 8-bit offset.
1133     *
1134     * The branch distance is a signed code-unit offset, which we need to
1135     * double to get a byte offset.
1136     */
1137    /* goto +AA */
1138    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1139    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1140    mov     r9, r9, lsl #1              @ r9<- byte offset
1141    bmi     common_backwardBranch       @ backward branch, do periodic checks
1142#if defined(WITH_JIT)
1143    GET_JIT_PROF_TABLE(r0)
1144    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1145    cmp     r0,#0
1146    bne     common_updateProfile
1147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1148    GOTO_OPCODE(ip)                     @ jump to next instruction
1149#else
1150    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1152    GOTO_OPCODE(ip)                     @ jump to next instruction
1153#endif
1154
1155/* ------------------------------ */
1156    .balign 64
1157.L_OP_GOTO_16: /* 0x29 */
1158/* File: armv5te/OP_GOTO_16.S */
1159    /*
1160     * Unconditional branch, 16-bit offset.
1161     *
1162     * The branch distance is a signed code-unit offset, which we need to
1163     * double to get a byte offset.
1164     */
1165    /* goto/16 +AAAA */
1166    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1167    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1168    bmi     common_backwardBranch       @ backward branch, do periodic checks
1169#if defined(WITH_JIT)
1170    GET_JIT_PROF_TABLE(r0)
1171    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1172    cmp     r0,#0
1173    bne     common_updateProfile
1174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1175    GOTO_OPCODE(ip)                     @ jump to next instruction
1176#else
1177    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1179    GOTO_OPCODE(ip)                     @ jump to next instruction
1180#endif
1181
1182/* ------------------------------ */
1183    .balign 64
1184.L_OP_GOTO_32: /* 0x2a */
1185/* File: armv5te/OP_GOTO_32.S */
1186    /*
1187     * Unconditional branch, 32-bit offset.
1188     *
1189     * The branch distance is a signed code-unit offset, which we need to
1190     * double to get a byte offset.
1191     *
1192     * Unlike most opcodes, this one is allowed to branch to itself, so
1193     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1194     * instruction doesn't affect the V flag, so we need to clear it
1195     * explicitly.
1196     */
1197    /* goto/32 +AAAAAAAA */
1198    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1199    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1200    cmp     ip, ip                      @ (clear V flag during stall)
1201    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1202    mov     r9, r0, asl #1              @ r9<- byte offset
1203    ble     common_backwardBranch       @ backward branch, do periodic checks
1204#if defined(WITH_JIT)
1205    GET_JIT_PROF_TABLE(r0)
1206    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1207    cmp     r0,#0
1208    bne     common_updateProfile
1209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1210    GOTO_OPCODE(ip)                     @ jump to next instruction
1211#else
1212    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1213    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1214    GOTO_OPCODE(ip)                     @ jump to next instruction
1215#endif
1216
1217/* ------------------------------ */
1218    .balign 64
1219.L_OP_PACKED_SWITCH: /* 0x2b */
1220/* File: armv5te/OP_PACKED_SWITCH.S */
1221    /*
1222     * Handle a packed-switch or sparse-switch instruction.  In both cases
1223     * we decode it and hand it off to a helper function.
1224     *
1225     * We don't really expect backward branches in a switch statement, but
1226     * they're perfectly legal, so we check for them here.
1227     *
1228     * for: packed-switch, sparse-switch
1229     */
1230    /* op vAA, +BBBB */
1231    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1232    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1233    mov     r3, rINST, lsr #8           @ r3<- AA
1234    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1235    GET_VREG(r1, r3)                    @ r1<- vAA
1236    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1237    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1238    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1239    bmi     common_backwardBranch       @ backward branch, do periodic checks
1240    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1241#if defined(WITH_JIT)
1242    GET_JIT_PROF_TABLE(r0)
1243    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1244    cmp     r0,#0
1245    bne     common_updateProfile
1246    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1247    GOTO_OPCODE(ip)                     @ jump to next instruction
1248#else
1249    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1250    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1251    GOTO_OPCODE(ip)                     @ jump to next instruction
1252#endif
1253
1254/* ------------------------------ */
1255    .balign 64
1256.L_OP_SPARSE_SWITCH: /* 0x2c */
1257/* File: armv5te/OP_SPARSE_SWITCH.S */
1258/* File: armv5te/OP_PACKED_SWITCH.S */
1259    /*
1260     * Handle a packed-switch or sparse-switch instruction.  In both cases
1261     * we decode it and hand it off to a helper function.
1262     *
1263     * We don't really expect backward branches in a switch statement, but
1264     * they're perfectly legal, so we check for them here.
1265     *
1266     * for: packed-switch, sparse-switch
1267     */
1268    /* op vAA, +BBBB */
1269    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1270    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1271    mov     r3, rINST, lsr #8           @ r3<- AA
1272    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1273    GET_VREG(r1, r3)                    @ r1<- vAA
1274    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1275    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1276    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1277    bmi     common_backwardBranch       @ backward branch, do periodic checks
1278    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1279#if defined(WITH_JIT)
1280    GET_JIT_PROF_TABLE(r0)
1281    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1282    cmp     r0,#0
1283    bne     common_updateProfile
1284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1285    GOTO_OPCODE(ip)                     @ jump to next instruction
1286#else
1287    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1288    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1289    GOTO_OPCODE(ip)                     @ jump to next instruction
1290#endif
1291
1292
1293/* ------------------------------ */
1294    .balign 64
1295.L_OP_CMPL_FLOAT: /* 0x2d */
1296/* File: arm-vfp/OP_CMPL_FLOAT.S */
1297    /*
1298     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1299     * destination register based on the results of the comparison.
1300     *
1301     * int compare(x, y) {
1302     *     if (x == y) {
1303     *         return 0;
1304     *     } else if (x > y) {
1305     *         return 1;
1306     *     } else if (x < y) {
1307     *         return -1;
1308     *     } else {
1309     *         return -1;
1310     *     }
1311     * }
1312     */
1313    /* op vAA, vBB, vCC */
1314    FETCH(r0, 1)                        @ r0<- CCBB
1315    mov     r9, rINST, lsr #8           @ r9<- AA
1316    and     r2, r0, #255                @ r2<- BB
1317    mov     r3, r0, lsr #8              @ r3<- CC
1318    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1319    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1320    flds    s0, [r2]                    @ s0<- vBB
1321    flds    s1, [r3]                    @ s1<- vCC
1322    fcmpes  s0, s1                      @ compare (vBB, vCC)
1323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1324    mvn     r0, #0                      @ r0<- -1 (default)
1325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1326    fmstat                              @ export status flags
1327    movgt   r0, #1                      @ (greater than) r1<- 1
1328    moveq   r0, #0                      @ (equal) r1<- 0
1329    b       .LOP_CMPL_FLOAT_finish          @ argh
1330
1331
1332/* ------------------------------ */
1333    .balign 64
1334.L_OP_CMPG_FLOAT: /* 0x2e */
1335/* File: arm-vfp/OP_CMPG_FLOAT.S */
1336    /*
1337     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1338     * destination register based on the results of the comparison.
1339     *
1340     * int compare(x, y) {
1341     *     if (x == y) {
1342     *         return 0;
1343     *     } else if (x < y) {
1344     *         return -1;
1345     *     } else if (x > y) {
1346     *         return 1;
1347     *     } else {
1348     *         return 1;
1349     *     }
1350     * }
1351     */
1352    /* op vAA, vBB, vCC */
1353    FETCH(r0, 1)                        @ r0<- CCBB
1354    mov     r9, rINST, lsr #8           @ r9<- AA
1355    and     r2, r0, #255                @ r2<- BB
1356    mov     r3, r0, lsr #8              @ r3<- CC
1357    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1358    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1359    flds    s0, [r2]                    @ s0<- vBB
1360    flds    s1, [r3]                    @ s1<- vCC
1361    fcmpes  s0, s1                      @ compare (vBB, vCC)
1362    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1363    mov     r0, #1                      @ r0<- 1 (default)
1364    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1365    fmstat                              @ export status flags
1366    mvnmi   r0, #0                      @ (less than) r1<- -1
1367    moveq   r0, #0                      @ (equal) r1<- 0
1368    b       .LOP_CMPG_FLOAT_finish          @ argh
1369
1370
1371/* ------------------------------ */
1372    .balign 64
1373.L_OP_CMPL_DOUBLE: /* 0x2f */
1374/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1375    /*
1376     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1377     * destination register based on the results of the comparison.
1378     *
1379     * int compare(x, y) {
1380     *     if (x == y) {
1381     *         return 0;
1382     *     } else if (x > y) {
1383     *         return 1;
1384     *     } else if (x < y) {
1385     *         return -1;
1386     *     } else {
1387     *         return -1;
1388     *     }
1389     * }
1390     */
1391    /* op vAA, vBB, vCC */
1392    FETCH(r0, 1)                        @ r0<- CCBB
1393    mov     r9, rINST, lsr #8           @ r9<- AA
1394    and     r2, r0, #255                @ r2<- BB
1395    mov     r3, r0, lsr #8              @ r3<- CC
1396    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1397    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1398    fldd    d0, [r2]                    @ d0<- vBB
1399    fldd    d1, [r3]                    @ d1<- vCC
1400    fcmped  d0, d1                      @ compare (vBB, vCC)
1401    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1402    mvn     r0, #0                      @ r0<- -1 (default)
1403    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1404    fmstat                              @ export status flags
1405    movgt   r0, #1                      @ (greater than) r1<- 1
1406    moveq   r0, #0                      @ (equal) r1<- 0
1407    b       .LOP_CMPL_DOUBLE_finish          @ argh
1408
1409
1410/* ------------------------------ */
1411    .balign 64
1412.L_OP_CMPG_DOUBLE: /* 0x30 */
1413/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1414    /*
1415     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1416     * destination register based on the results of the comparison.
1417     *
1418     * int compare(x, y) {
1419     *     if (x == y) {
1420     *         return 0;
1421     *     } else if (x < y) {
1422     *         return -1;
1423     *     } else if (x > y) {
1424     *         return 1;
1425     *     } else {
1426     *         return 1;
1427     *     }
1428     * }
1429     */
1430    /* op vAA, vBB, vCC */
1431    FETCH(r0, 1)                        @ r0<- CCBB
1432    mov     r9, rINST, lsr #8           @ r9<- AA
1433    and     r2, r0, #255                @ r2<- BB
1434    mov     r3, r0, lsr #8              @ r3<- CC
1435    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1436    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1437    fldd    d0, [r2]                    @ d0<- vBB
1438    fldd    d1, [r3]                    @ d1<- vCC
1439    fcmped  d0, d1                      @ compare (vBB, vCC)
1440    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1441    mov     r0, #1                      @ r0<- 1 (default)
1442    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1443    fmstat                              @ export status flags
1444    mvnmi   r0, #0                      @ (less than) r1<- -1
1445    moveq   r0, #0                      @ (equal) r1<- 0
1446    b       .LOP_CMPG_DOUBLE_finish          @ argh
1447
1448
1449/* ------------------------------ */
1450    .balign 64
1451.L_OP_CMP_LONG: /* 0x31 */
1452/* File: armv5te/OP_CMP_LONG.S */
1453    /*
1454     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1455     * register based on the results of the comparison.
1456     *
1457     * We load the full values with LDM, but in practice many values could
1458     * be resolved by only looking at the high word.  This could be made
1459     * faster or slower by splitting the LDM into a pair of LDRs.
1460     *
1461     * If we just wanted to set condition flags, we could do this:
1462     *  subs    ip, r0, r2
1463     *  sbcs    ip, r1, r3
1464     *  subeqs  ip, r0, r2
1465     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1466     * integer value, which we can do with 2 conditional mov/mvn instructions
1467     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1468     * us a constant 5-cycle path plus a branch at the end to the
1469     * instruction epilogue code.  The multi-compare approach below needs
1470     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1471     * in the worst case (the 64-bit values are equal).
1472     */
1473    /* cmp-long vAA, vBB, vCC */
1474    FETCH(r0, 1)                        @ r0<- CCBB
1475    mov     r9, rINST, lsr #8           @ r9<- AA
1476    and     r2, r0, #255                @ r2<- BB
1477    mov     r3, r0, lsr #8              @ r3<- CC
1478    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1479    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1480    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1481    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1482    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1483    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1484    bgt     .LOP_CMP_LONG_greater
1485    subs    r1, r0, r2                  @ r1<- r0 - r2
1486    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1487    bne     .LOP_CMP_LONG_less
1488    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1489
1490/* ------------------------------ */
1491    .balign 64
1492.L_OP_IF_EQ: /* 0x32 */
1493/* File: armv6t2/OP_IF_EQ.S */
1494/* File: armv6t2/bincmp.S */
1495    /*
1496     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1497     * fragment that specifies the *reverse* comparison to perform, e.g.
1498     * for "if-le" you would use "gt".
1499     *
1500     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1501     */
1502    /* if-cmp vA, vB, +CCCC */
1503    mov     r1, rINST, lsr #12          @ r1<- B
1504    ubfx    r0, rINST, #8, #4           @ r0<- A
1505    GET_VREG(r3, r1)                    @ r3<- vB
1506    GET_VREG(r2, r0)                    @ r2<- vA
1507    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1508    cmp     r2, r3                      @ compare (vA, vB)
1509    bne  1f                      @ branch to 1 if comparison failed
1510    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1511    movs    r9, r9, asl #1              @ convert to bytes, check sign
1512    bmi     common_backwardBranch       @ yes, do periodic checks
15131:
1514#if defined(WITH_JIT)
1515    GET_JIT_PROF_TABLE(r0)
1516    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1517    b        common_testUpdateProfile
1518#else
1519    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1521    GOTO_OPCODE(ip)                     @ jump to next instruction
1522#endif
1523
1524
1525/* ------------------------------ */
1526    .balign 64
1527.L_OP_IF_NE: /* 0x33 */
1528/* File: armv6t2/OP_IF_NE.S */
1529/* File: armv6t2/bincmp.S */
1530    /*
1531     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1532     * fragment that specifies the *reverse* comparison to perform, e.g.
1533     * for "if-le" you would use "gt".
1534     *
1535     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1536     */
1537    /* if-cmp vA, vB, +CCCC */
1538    mov     r1, rINST, lsr #12          @ r1<- B
1539    ubfx    r0, rINST, #8, #4           @ r0<- A
1540    GET_VREG(r3, r1)                    @ r3<- vB
1541    GET_VREG(r2, r0)                    @ r2<- vA
1542    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1543    cmp     r2, r3                      @ compare (vA, vB)
1544    beq  1f                      @ branch to 1 if comparison failed
1545    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1546    movs    r9, r9, asl #1              @ convert to bytes, check sign
1547    bmi     common_backwardBranch       @ yes, do periodic checks
15481:
1549#if defined(WITH_JIT)
1550    GET_JIT_PROF_TABLE(r0)
1551    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1552    b        common_testUpdateProfile
1553#else
1554    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1555    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1556    GOTO_OPCODE(ip)                     @ jump to next instruction
1557#endif
1558
1559
1560/* ------------------------------ */
1561    .balign 64
1562.L_OP_IF_LT: /* 0x34 */
1563/* File: armv6t2/OP_IF_LT.S */
1564/* File: armv6t2/bincmp.S */
1565    /*
1566     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1567     * fragment that specifies the *reverse* comparison to perform, e.g.
1568     * for "if-le" you would use "gt".
1569     *
1570     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1571     */
1572    /* if-cmp vA, vB, +CCCC */
1573    mov     r1, rINST, lsr #12          @ r1<- B
1574    ubfx    r0, rINST, #8, #4           @ r0<- A
1575    GET_VREG(r3, r1)                    @ r3<- vB
1576    GET_VREG(r2, r0)                    @ r2<- vA
1577    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1578    cmp     r2, r3                      @ compare (vA, vB)
1579    bge  1f                      @ branch to 1 if comparison failed
1580    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1581    movs    r9, r9, asl #1              @ convert to bytes, check sign
1582    bmi     common_backwardBranch       @ yes, do periodic checks
15831:
1584#if defined(WITH_JIT)
1585    GET_JIT_PROF_TABLE(r0)
1586    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1587    b        common_testUpdateProfile
1588#else
1589    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1591    GOTO_OPCODE(ip)                     @ jump to next instruction
1592#endif
1593
1594
1595/* ------------------------------ */
1596    .balign 64
1597.L_OP_IF_GE: /* 0x35 */
1598/* File: armv6t2/OP_IF_GE.S */
1599/* File: armv6t2/bincmp.S */
1600    /*
1601     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1602     * fragment that specifies the *reverse* comparison to perform, e.g.
1603     * for "if-le" you would use "gt".
1604     *
1605     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1606     */
1607    /* if-cmp vA, vB, +CCCC */
1608    mov     r1, rINST, lsr #12          @ r1<- B
1609    ubfx    r0, rINST, #8, #4           @ r0<- A
1610    GET_VREG(r3, r1)                    @ r3<- vB
1611    GET_VREG(r2, r0)                    @ r2<- vA
1612    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1613    cmp     r2, r3                      @ compare (vA, vB)
1614    blt  1f                      @ branch to 1 if comparison failed
1615    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1616    movs    r9, r9, asl #1              @ convert to bytes, check sign
1617    bmi     common_backwardBranch       @ yes, do periodic checks
16181:
1619#if defined(WITH_JIT)
1620    GET_JIT_PROF_TABLE(r0)
1621    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1622    b        common_testUpdateProfile
1623#else
1624    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1626    GOTO_OPCODE(ip)                     @ jump to next instruction
1627#endif
1628
1629
1630/* ------------------------------ */
1631    .balign 64
1632.L_OP_IF_GT: /* 0x36 */
1633/* File: armv6t2/OP_IF_GT.S */
1634/* File: armv6t2/bincmp.S */
1635    /*
1636     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1637     * fragment that specifies the *reverse* comparison to perform, e.g.
1638     * for "if-le" you would use "gt".
1639     *
1640     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1641     */
1642    /* if-cmp vA, vB, +CCCC */
1643    mov     r1, rINST, lsr #12          @ r1<- B
1644    ubfx    r0, rINST, #8, #4           @ r0<- A
1645    GET_VREG(r3, r1)                    @ r3<- vB
1646    GET_VREG(r2, r0)                    @ r2<- vA
1647    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1648    cmp     r2, r3                      @ compare (vA, vB)
1649    ble  1f                      @ branch to 1 if comparison failed
1650    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1651    movs    r9, r9, asl #1              @ convert to bytes, check sign
1652    bmi     common_backwardBranch       @ yes, do periodic checks
16531:
1654#if defined(WITH_JIT)
1655    GET_JIT_PROF_TABLE(r0)
1656    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1657    b        common_testUpdateProfile
1658#else
1659    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1660    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1661    GOTO_OPCODE(ip)                     @ jump to next instruction
1662#endif
1663
1664
1665/* ------------------------------ */
1666    .balign 64
1667.L_OP_IF_LE: /* 0x37 */
1668/* File: armv6t2/OP_IF_LE.S */
1669/* File: armv6t2/bincmp.S */
1670    /*
1671     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1672     * fragment that specifies the *reverse* comparison to perform, e.g.
1673     * for "if-le" you would use "gt".
1674     *
1675     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1676     */
1677    /* if-cmp vA, vB, +CCCC */
1678    mov     r1, rINST, lsr #12          @ r1<- B
1679    ubfx    r0, rINST, #8, #4           @ r0<- A
1680    GET_VREG(r3, r1)                    @ r3<- vB
1681    GET_VREG(r2, r0)                    @ r2<- vA
1682    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1683    cmp     r2, r3                      @ compare (vA, vB)
1684    bgt  1f                      @ branch to 1 if comparison failed
1685    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1686    movs    r9, r9, asl #1              @ convert to bytes, check sign
1687    bmi     common_backwardBranch       @ yes, do periodic checks
16881:
1689#if defined(WITH_JIT)
1690    GET_JIT_PROF_TABLE(r0)
1691    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1692    b        common_testUpdateProfile
1693#else
1694    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1695    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1696    GOTO_OPCODE(ip)                     @ jump to next instruction
1697#endif
1698
1699
1700/* ------------------------------ */
1701    .balign 64
1702.L_OP_IF_EQZ: /* 0x38 */
1703/* File: armv5te/OP_IF_EQZ.S */
1704/* File: armv5te/zcmp.S */
1705    /*
1706     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1707     * fragment that specifies the *reverse* comparison to perform, e.g.
1708     * for "if-le" you would use "gt".
1709     *
1710     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1711     */
1712    /* if-cmp vAA, +BBBB */
1713    mov     r0, rINST, lsr #8           @ r0<- AA
1714    GET_VREG(r2, r0)                    @ r2<- vAA
1715    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1716    cmp     r2, #0                      @ compare (vA, 0)
1717    bne  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       @ backward branch, 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    cmp     r0,#0
1726    bne     common_updateProfile
1727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1728    GOTO_OPCODE(ip)                     @ jump to next instruction
1729#else
1730    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1731    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1732    GOTO_OPCODE(ip)                     @ jump to next instruction
1733#endif
1734
1735
1736/* ------------------------------ */
1737    .balign 64
1738.L_OP_IF_NEZ: /* 0x39 */
1739/* File: armv5te/OP_IF_NEZ.S */
1740/* File: armv5te/zcmp.S */
1741    /*
1742     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1743     * fragment that specifies the *reverse* comparison to perform, e.g.
1744     * for "if-le" you would use "gt".
1745     *
1746     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1747     */
1748    /* if-cmp vAA, +BBBB */
1749    mov     r0, rINST, lsr #8           @ r0<- AA
1750    GET_VREG(r2, r0)                    @ r2<- vAA
1751    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1752    cmp     r2, #0                      @ compare (vA, 0)
1753    beq  1f                      @ branch to 1 if comparison failed
1754    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1755    movs    r9, r9, asl #1              @ convert to bytes, check sign
1756    bmi     common_backwardBranch       @ backward branch, do periodic checks
17571:
1758#if defined(WITH_JIT)
1759    GET_JIT_PROF_TABLE(r0)
1760    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1761    cmp     r0,#0
1762    bne     common_updateProfile
1763    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1764    GOTO_OPCODE(ip)                     @ jump to next instruction
1765#else
1766    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1767    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1768    GOTO_OPCODE(ip)                     @ jump to next instruction
1769#endif
1770
1771
1772/* ------------------------------ */
1773    .balign 64
1774.L_OP_IF_LTZ: /* 0x3a */
1775/* File: armv5te/OP_IF_LTZ.S */
1776/* File: armv5te/zcmp.S */
1777    /*
1778     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1779     * fragment that specifies the *reverse* comparison to perform, e.g.
1780     * for "if-le" you would use "gt".
1781     *
1782     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1783     */
1784    /* if-cmp vAA, +BBBB */
1785    mov     r0, rINST, lsr #8           @ r0<- AA
1786    GET_VREG(r2, r0)                    @ r2<- vAA
1787    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1788    cmp     r2, #0                      @ compare (vA, 0)
1789    bge  1f                      @ branch to 1 if comparison failed
1790    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1791    movs    r9, r9, asl #1              @ convert to bytes, check sign
1792    bmi     common_backwardBranch       @ backward branch, do periodic checks
17931:
1794#if defined(WITH_JIT)
1795    GET_JIT_PROF_TABLE(r0)
1796    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1797    cmp     r0,#0
1798    bne     common_updateProfile
1799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1800    GOTO_OPCODE(ip)                     @ jump to next instruction
1801#else
1802    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1804    GOTO_OPCODE(ip)                     @ jump to next instruction
1805#endif
1806
1807
1808/* ------------------------------ */
1809    .balign 64
1810.L_OP_IF_GEZ: /* 0x3b */
1811/* File: armv5te/OP_IF_GEZ.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    blt  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    .balign 64
1846.L_OP_IF_GTZ: /* 0x3c */
1847/* File: armv5te/OP_IF_GTZ.S */
1848/* File: armv5te/zcmp.S */
1849    /*
1850     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1851     * fragment that specifies the *reverse* comparison to perform, e.g.
1852     * for "if-le" you would use "gt".
1853     *
1854     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1855     */
1856    /* if-cmp vAA, +BBBB */
1857    mov     r0, rINST, lsr #8           @ r0<- AA
1858    GET_VREG(r2, r0)                    @ r2<- vAA
1859    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1860    cmp     r2, #0                      @ compare (vA, 0)
1861    ble  1f                      @ branch to 1 if comparison failed
1862    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1863    movs    r9, r9, asl #1              @ convert to bytes, check sign
1864    bmi     common_backwardBranch       @ backward branch, do periodic checks
18651:
1866#if defined(WITH_JIT)
1867    GET_JIT_PROF_TABLE(r0)
1868    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1869    cmp     r0,#0
1870    bne     common_updateProfile
1871    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1872    GOTO_OPCODE(ip)                     @ jump to next instruction
1873#else
1874    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1875    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1876    GOTO_OPCODE(ip)                     @ jump to next instruction
1877#endif
1878
1879
1880/* ------------------------------ */
1881    .balign 64
1882.L_OP_IF_LEZ: /* 0x3d */
1883/* File: armv5te/OP_IF_LEZ.S */
1884/* File: armv5te/zcmp.S */
1885    /*
1886     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1887     * fragment that specifies the *reverse* comparison to perform, e.g.
1888     * for "if-le" you would use "gt".
1889     *
1890     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1891     */
1892    /* if-cmp vAA, +BBBB */
1893    mov     r0, rINST, lsr #8           @ r0<- AA
1894    GET_VREG(r2, r0)                    @ r2<- vAA
1895    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1896    cmp     r2, #0                      @ compare (vA, 0)
1897    bgt  1f                      @ branch to 1 if comparison failed
1898    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1899    movs    r9, r9, asl #1              @ convert to bytes, check sign
1900    bmi     common_backwardBranch       @ backward branch, do periodic checks
19011:
1902#if defined(WITH_JIT)
1903    GET_JIT_PROF_TABLE(r0)
1904    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1905    cmp     r0,#0
1906    bne     common_updateProfile
1907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1908    GOTO_OPCODE(ip)                     @ jump to next instruction
1909#else
1910    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1912    GOTO_OPCODE(ip)                     @ jump to next instruction
1913#endif
1914
1915
1916/* ------------------------------ */
1917    .balign 64
1918.L_OP_UNUSED_3E: /* 0x3e */
1919/* File: armv5te/OP_UNUSED_3E.S */
1920/* File: armv5te/unused.S */
1921    bl      common_abort
1922
1923
1924/* ------------------------------ */
1925    .balign 64
1926.L_OP_UNUSED_3F: /* 0x3f */
1927/* File: armv5te/OP_UNUSED_3F.S */
1928/* File: armv5te/unused.S */
1929    bl      common_abort
1930
1931
1932/* ------------------------------ */
1933    .balign 64
1934.L_OP_UNUSED_40: /* 0x40 */
1935/* File: armv5te/OP_UNUSED_40.S */
1936/* File: armv5te/unused.S */
1937    bl      common_abort
1938
1939
1940/* ------------------------------ */
1941    .balign 64
1942.L_OP_UNUSED_41: /* 0x41 */
1943/* File: armv5te/OP_UNUSED_41.S */
1944/* File: armv5te/unused.S */
1945    bl      common_abort
1946
1947
1948/* ------------------------------ */
1949    .balign 64
1950.L_OP_UNUSED_42: /* 0x42 */
1951/* File: armv5te/OP_UNUSED_42.S */
1952/* File: armv5te/unused.S */
1953    bl      common_abort
1954
1955
1956/* ------------------------------ */
1957    .balign 64
1958.L_OP_UNUSED_43: /* 0x43 */
1959/* File: armv5te/OP_UNUSED_43.S */
1960/* File: armv5te/unused.S */
1961    bl      common_abort
1962
1963
1964/* ------------------------------ */
1965    .balign 64
1966.L_OP_AGET: /* 0x44 */
1967/* File: armv5te/OP_AGET.S */
1968    /*
1969     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1970     *
1971     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1972     * instructions.  We use a pair of FETCH_Bs instead.
1973     *
1974     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1975     */
1976    /* op vAA, vBB, vCC */
1977    FETCH_B(r2, 1, 0)                   @ r2<- BB
1978    mov     r9, rINST, lsr #8           @ r9<- AA
1979    FETCH_B(r3, 1, 1)                   @ r3<- CC
1980    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1981    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1982    cmp     r0, #0                      @ null array object?
1983    beq     common_errNullObject        @ yes, bail
1984    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1985    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1986    cmp     r1, r3                      @ compare unsigned index, length
1987    bcs     common_errArrayIndex        @ index >= length, bail
1988    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1989    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1990    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1991    SET_VREG(r2, r9)                    @ vAA<- r2
1992    GOTO_OPCODE(ip)                     @ jump to next instruction
1993
1994/* ------------------------------ */
1995    .balign 64
1996.L_OP_AGET_WIDE: /* 0x45 */
1997/* File: armv5te/OP_AGET_WIDE.S */
1998    /*
1999     * Array get, 64 bits.  vAA <- vBB[vCC].
2000     *
2001     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2002     */
2003    /* aget-wide vAA, vBB, vCC */
2004    FETCH(r0, 1)                        @ r0<- CCBB
2005    mov     r9, rINST, lsr #8           @ r9<- AA
2006    and     r2, r0, #255                @ r2<- BB
2007    mov     r3, r0, lsr #8              @ r3<- CC
2008    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2009    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2010    cmp     r0, #0                      @ null array object?
2011    beq     common_errNullObject        @ yes, bail
2012    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2013    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2014    cmp     r1, r3                      @ compare unsigned index, length
2015    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2016    b       common_errArrayIndex        @ index >= length, bail
2017    @ May want to swap the order of these two branches depending on how the
2018    @ branch prediction (if any) handles conditional forward branches vs.
2019    @ unconditional forward branches.
2020
2021/* ------------------------------ */
2022    .balign 64
2023.L_OP_AGET_OBJECT: /* 0x46 */
2024/* File: armv5te/OP_AGET_OBJECT.S */
2025/* File: armv5te/OP_AGET.S */
2026    /*
2027     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2028     *
2029     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2030     * instructions.  We use a pair of FETCH_Bs instead.
2031     *
2032     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2033     */
2034    /* op vAA, vBB, vCC */
2035    FETCH_B(r2, 1, 0)                   @ r2<- BB
2036    mov     r9, rINST, lsr #8           @ r9<- AA
2037    FETCH_B(r3, 1, 1)                   @ r3<- CC
2038    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2039    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2040    cmp     r0, #0                      @ null array object?
2041    beq     common_errNullObject        @ yes, bail
2042    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2043    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2044    cmp     r1, r3                      @ compare unsigned index, length
2045    bcs     common_errArrayIndex        @ index >= length, bail
2046    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2047    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2048    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2049    SET_VREG(r2, r9)                    @ vAA<- r2
2050    GOTO_OPCODE(ip)                     @ jump to next instruction
2051
2052
2053/* ------------------------------ */
2054    .balign 64
2055.L_OP_AGET_BOOLEAN: /* 0x47 */
2056/* File: armv5te/OP_AGET_BOOLEAN.S */
2057/* File: armv5te/OP_AGET.S */
2058    /*
2059     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2060     *
2061     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2062     * instructions.  We use a pair of FETCH_Bs instead.
2063     *
2064     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2065     */
2066    /* op vAA, vBB, vCC */
2067    FETCH_B(r2, 1, 0)                   @ r2<- BB
2068    mov     r9, rINST, lsr #8           @ r9<- AA
2069    FETCH_B(r3, 1, 1)                   @ r3<- CC
2070    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2071    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2072    cmp     r0, #0                      @ null array object?
2073    beq     common_errNullObject        @ yes, bail
2074    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2075    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2076    cmp     r1, r3                      @ compare unsigned index, length
2077    bcs     common_errArrayIndex        @ index >= length, bail
2078    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2079    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2080    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2081    SET_VREG(r2, r9)                    @ vAA<- r2
2082    GOTO_OPCODE(ip)                     @ jump to next instruction
2083
2084
2085/* ------------------------------ */
2086    .balign 64
2087.L_OP_AGET_BYTE: /* 0x48 */
2088/* File: armv5te/OP_AGET_BYTE.S */
2089/* File: armv5te/OP_AGET.S */
2090    /*
2091     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2092     *
2093     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2094     * instructions.  We use a pair of FETCH_Bs instead.
2095     *
2096     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2097     */
2098    /* op vAA, vBB, vCC */
2099    FETCH_B(r2, 1, 0)                   @ r2<- BB
2100    mov     r9, rINST, lsr #8           @ r9<- AA
2101    FETCH_B(r3, 1, 1)                   @ r3<- CC
2102    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2103    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2104    cmp     r0, #0                      @ null array object?
2105    beq     common_errNullObject        @ yes, bail
2106    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2107    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2108    cmp     r1, r3                      @ compare unsigned index, length
2109    bcs     common_errArrayIndex        @ index >= length, bail
2110    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2111    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2113    SET_VREG(r2, r9)                    @ vAA<- r2
2114    GOTO_OPCODE(ip)                     @ jump to next instruction
2115
2116
2117/* ------------------------------ */
2118    .balign 64
2119.L_OP_AGET_CHAR: /* 0x49 */
2120/* File: armv5te/OP_AGET_CHAR.S */
2121/* File: armv5te/OP_AGET.S */
2122    /*
2123     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2124     *
2125     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2126     * instructions.  We use a pair of FETCH_Bs instead.
2127     *
2128     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2129     */
2130    /* op vAA, vBB, vCC */
2131    FETCH_B(r2, 1, 0)                   @ r2<- BB
2132    mov     r9, rINST, lsr #8           @ r9<- AA
2133    FETCH_B(r3, 1, 1)                   @ r3<- CC
2134    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2135    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2136    cmp     r0, #0                      @ null array object?
2137    beq     common_errNullObject        @ yes, bail
2138    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2139    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2140    cmp     r1, r3                      @ compare unsigned index, length
2141    bcs     common_errArrayIndex        @ index >= length, bail
2142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2143    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2145    SET_VREG(r2, r9)                    @ vAA<- r2
2146    GOTO_OPCODE(ip)                     @ jump to next instruction
2147
2148
2149/* ------------------------------ */
2150    .balign 64
2151.L_OP_AGET_SHORT: /* 0x4a */
2152/* File: armv5te/OP_AGET_SHORT.S */
2153/* File: armv5te/OP_AGET.S */
2154    /*
2155     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2156     *
2157     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2158     * instructions.  We use a pair of FETCH_Bs instead.
2159     *
2160     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2161     */
2162    /* op vAA, vBB, vCC */
2163    FETCH_B(r2, 1, 0)                   @ r2<- BB
2164    mov     r9, rINST, lsr #8           @ r9<- AA
2165    FETCH_B(r3, 1, 1)                   @ r3<- CC
2166    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2167    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2168    cmp     r0, #0                      @ null array object?
2169    beq     common_errNullObject        @ yes, bail
2170    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2171    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2172    cmp     r1, r3                      @ compare unsigned index, length
2173    bcs     common_errArrayIndex        @ index >= length, bail
2174    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2175    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2177    SET_VREG(r2, r9)                    @ vAA<- r2
2178    GOTO_OPCODE(ip)                     @ jump to next instruction
2179
2180
2181/* ------------------------------ */
2182    .balign 64
2183.L_OP_APUT: /* 0x4b */
2184/* File: armv5te/OP_APUT.S */
2185    /*
2186     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2187     *
2188     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2189     * instructions.  We use a pair of FETCH_Bs instead.
2190     *
2191     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2192     */
2193    /* op vAA, vBB, vCC */
2194    FETCH_B(r2, 1, 0)                   @ r2<- BB
2195    mov     r9, rINST, lsr #8           @ r9<- AA
2196    FETCH_B(r3, 1, 1)                   @ r3<- CC
2197    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2198    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2199    cmp     r0, #0                      @ null array object?
2200    beq     common_errNullObject        @ yes, bail
2201    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2202    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2203    cmp     r1, r3                      @ compare unsigned index, length
2204    bcs     common_errArrayIndex        @ index >= length, bail
2205    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2206    GET_VREG(r2, r9)                    @ r2<- vAA
2207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2208    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2209    GOTO_OPCODE(ip)                     @ jump to next instruction
2210
2211/* ------------------------------ */
2212    .balign 64
2213.L_OP_APUT_WIDE: /* 0x4c */
2214/* File: armv5te/OP_APUT_WIDE.S */
2215    /*
2216     * Array put, 64 bits.  vBB[vCC] <- vAA.
2217     *
2218     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2219     */
2220    /* aput-wide vAA, vBB, vCC */
2221    FETCH(r0, 1)                        @ r0<- CCBB
2222    mov     r9, rINST, lsr #8           @ r9<- AA
2223    and     r2, r0, #255                @ r2<- BB
2224    mov     r3, r0, lsr #8              @ r3<- CC
2225    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2226    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2227    cmp     r0, #0                      @ null array object?
2228    beq     common_errNullObject        @ yes, bail
2229    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2230    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2231    cmp     r1, r3                      @ compare unsigned index, length
2232    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2233    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2234    b       common_errArrayIndex        @ index >= length, bail
2235    @ May want to swap the order of these two branches depending on how the
2236    @ branch prediction (if any) handles conditional forward branches vs.
2237    @ unconditional forward branches.
2238
2239/* ------------------------------ */
2240    .balign 64
2241.L_OP_APUT_OBJECT: /* 0x4d */
2242/* File: armv5te/OP_APUT_OBJECT.S */
2243    /*
2244     * Store an object into an array.  vBB[vCC] <- vAA.
2245     *
2246     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2247     * instructions.  We use a pair of FETCH_Bs instead.
2248     */
2249    /* op vAA, vBB, vCC */
2250    FETCH(r0, 1)                        @ r0<- CCBB
2251    mov     r9, rINST, lsr #8           @ r9<- AA
2252    and     r2, r0, #255                @ r2<- BB
2253    mov     r3, r0, lsr #8              @ r3<- CC
2254    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2255    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2256    cmp     r1, #0                      @ null array object?
2257    GET_VREG(r9, r9)                    @ r9<- vAA
2258    beq     common_errNullObject        @ yes, bail
2259    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2260    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2261    cmp     r0, r3                      @ compare unsigned index, length
2262    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2263    b       common_errArrayIndex        @ index >= length, bail
2264
2265
2266/* ------------------------------ */
2267    .balign 64
2268.L_OP_APUT_BOOLEAN: /* 0x4e */
2269/* File: armv5te/OP_APUT_BOOLEAN.S */
2270/* File: armv5te/OP_APUT.S */
2271    /*
2272     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2273     *
2274     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2275     * instructions.  We use a pair of FETCH_Bs instead.
2276     *
2277     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2278     */
2279    /* op vAA, vBB, vCC */
2280    FETCH_B(r2, 1, 0)                   @ r2<- BB
2281    mov     r9, rINST, lsr #8           @ r9<- AA
2282    FETCH_B(r3, 1, 1)                   @ r3<- CC
2283    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2284    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2285    cmp     r0, #0                      @ null array object?
2286    beq     common_errNullObject        @ yes, bail
2287    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2288    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2289    cmp     r1, r3                      @ compare unsigned index, length
2290    bcs     common_errArrayIndex        @ index >= length, bail
2291    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2292    GET_VREG(r2, r9)                    @ r2<- vAA
2293    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2294    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2295    GOTO_OPCODE(ip)                     @ jump to next instruction
2296
2297
2298/* ------------------------------ */
2299    .balign 64
2300.L_OP_APUT_BYTE: /* 0x4f */
2301/* File: armv5te/OP_APUT_BYTE.S */
2302/* File: armv5te/OP_APUT.S */
2303    /*
2304     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2305     *
2306     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2307     * instructions.  We use a pair of FETCH_Bs instead.
2308     *
2309     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2310     */
2311    /* op vAA, vBB, vCC */
2312    FETCH_B(r2, 1, 0)                   @ r2<- BB
2313    mov     r9, rINST, lsr #8           @ r9<- AA
2314    FETCH_B(r3, 1, 1)                   @ r3<- CC
2315    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2316    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2317    cmp     r0, #0                      @ null array object?
2318    beq     common_errNullObject        @ yes, bail
2319    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2320    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2321    cmp     r1, r3                      @ compare unsigned index, length
2322    bcs     common_errArrayIndex        @ index >= length, bail
2323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2324    GET_VREG(r2, r9)                    @ r2<- vAA
2325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2326    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2327    GOTO_OPCODE(ip)                     @ jump to next instruction
2328
2329
2330/* ------------------------------ */
2331    .balign 64
2332.L_OP_APUT_CHAR: /* 0x50 */
2333/* File: armv5te/OP_APUT_CHAR.S */
2334/* File: armv5te/OP_APUT.S */
2335    /*
2336     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2337     *
2338     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2339     * instructions.  We use a pair of FETCH_Bs instead.
2340     *
2341     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2342     */
2343    /* op vAA, vBB, vCC */
2344    FETCH_B(r2, 1, 0)                   @ r2<- BB
2345    mov     r9, rINST, lsr #8           @ r9<- AA
2346    FETCH_B(r3, 1, 1)                   @ r3<- CC
2347    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2348    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2349    cmp     r0, #0                      @ null array object?
2350    beq     common_errNullObject        @ yes, bail
2351    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2352    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2353    cmp     r1, r3                      @ compare unsigned index, length
2354    bcs     common_errArrayIndex        @ index >= length, bail
2355    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2356    GET_VREG(r2, r9)                    @ r2<- vAA
2357    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2358    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2359    GOTO_OPCODE(ip)                     @ jump to next instruction
2360
2361
2362/* ------------------------------ */
2363    .balign 64
2364.L_OP_APUT_SHORT: /* 0x51 */
2365/* File: armv5te/OP_APUT_SHORT.S */
2366/* File: armv5te/OP_APUT.S */
2367    /*
2368     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2369     *
2370     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2371     * instructions.  We use a pair of FETCH_Bs instead.
2372     *
2373     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2374     */
2375    /* op vAA, vBB, vCC */
2376    FETCH_B(r2, 1, 0)                   @ r2<- BB
2377    mov     r9, rINST, lsr #8           @ r9<- AA
2378    FETCH_B(r3, 1, 1)                   @ r3<- CC
2379    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2380    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2381    cmp     r0, #0                      @ null array object?
2382    beq     common_errNullObject        @ yes, bail
2383    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2384    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2385    cmp     r1, r3                      @ compare unsigned index, length
2386    bcs     common_errArrayIndex        @ index >= length, bail
2387    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2388    GET_VREG(r2, r9)                    @ r2<- vAA
2389    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2390    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2391    GOTO_OPCODE(ip)                     @ jump to next instruction
2392
2393
2394/* ------------------------------ */
2395    .balign 64
2396.L_OP_IGET: /* 0x52 */
2397/* File: armv6t2/OP_IGET.S */
2398    /*
2399     * General 32-bit instance field get.
2400     *
2401     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2402     */
2403    /* op vA, vB, field@CCCC */
2404    mov     r0, rINST, lsr #12          @ r0<- B
2405    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2406    FETCH(r1, 1)                        @ r1<- field ref CCCC
2407    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2408    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2409    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2410    cmp     r0, #0                      @ is resolved entry null?
2411    bne     .LOP_IGET_finish          @ no, already resolved
24128:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2413    EXPORT_PC()                         @ resolve() could throw
2414    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2415    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2416    cmp     r0, #0
2417    bne     .LOP_IGET_finish
2418    b       common_exceptionThrown
2419
2420/* ------------------------------ */
2421    .balign 64
2422.L_OP_IGET_WIDE: /* 0x53 */
2423/* File: armv6t2/OP_IGET_WIDE.S */
2424    /*
2425     * Wide 32-bit instance field get.
2426     */
2427    /* iget-wide vA, vB, field@CCCC */
2428    mov     r0, rINST, lsr #12          @ r0<- B
2429    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2430    FETCH(r1, 1)                        @ r1<- field ref CCCC
2431    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2432    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2433    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2434    cmp     r0, #0                      @ is resolved entry null?
2435    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24368:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2437    EXPORT_PC()                         @ resolve() could throw
2438    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2439    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2440    cmp     r0, #0
2441    bne     .LOP_IGET_WIDE_finish
2442    b       common_exceptionThrown
2443
2444/* ------------------------------ */
2445    .balign 64
2446.L_OP_IGET_OBJECT: /* 0x54 */
2447/* File: armv5te/OP_IGET_OBJECT.S */
2448/* File: armv5te/OP_IGET.S */
2449    /*
2450     * General 32-bit instance field get.
2451     *
2452     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2453     */
2454    /* op vA, vB, field@CCCC */
2455    mov     r0, rINST, lsr #12          @ r0<- B
2456    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2457    FETCH(r1, 1)                        @ r1<- field ref CCCC
2458    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2459    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2460    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2461    cmp     r0, #0                      @ is resolved entry null?
2462    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24638:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2464    EXPORT_PC()                         @ resolve() could throw
2465    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2466    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2467    cmp     r0, #0
2468    bne     .LOP_IGET_OBJECT_finish
2469    b       common_exceptionThrown
2470
2471
2472/* ------------------------------ */
2473    .balign 64
2474.L_OP_IGET_BOOLEAN: /* 0x55 */
2475/* File: armv5te/OP_IGET_BOOLEAN.S */
2476@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2477/* File: armv5te/OP_IGET.S */
2478    /*
2479     * General 32-bit instance field get.
2480     *
2481     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2482     */
2483    /* op vA, vB, field@CCCC */
2484    mov     r0, rINST, lsr #12          @ r0<- B
2485    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2486    FETCH(r1, 1)                        @ r1<- field ref CCCC
2487    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2488    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2489    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2490    cmp     r0, #0                      @ is resolved entry null?
2491    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
24928:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2493    EXPORT_PC()                         @ resolve() could throw
2494    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2495    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2496    cmp     r0, #0
2497    bne     .LOP_IGET_BOOLEAN_finish
2498    b       common_exceptionThrown
2499
2500
2501/* ------------------------------ */
2502    .balign 64
2503.L_OP_IGET_BYTE: /* 0x56 */
2504/* File: armv5te/OP_IGET_BYTE.S */
2505@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2506/* File: armv5te/OP_IGET.S */
2507    /*
2508     * General 32-bit instance field get.
2509     *
2510     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2511     */
2512    /* op vA, vB, field@CCCC */
2513    mov     r0, rINST, lsr #12          @ r0<- B
2514    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2515    FETCH(r1, 1)                        @ r1<- field ref CCCC
2516    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2517    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2518    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2519    cmp     r0, #0                      @ is resolved entry null?
2520    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25218:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2522    EXPORT_PC()                         @ resolve() could throw
2523    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2524    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2525    cmp     r0, #0
2526    bne     .LOP_IGET_BYTE_finish
2527    b       common_exceptionThrown
2528
2529
2530/* ------------------------------ */
2531    .balign 64
2532.L_OP_IGET_CHAR: /* 0x57 */
2533/* File: armv5te/OP_IGET_CHAR.S */
2534@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2535/* File: armv5te/OP_IGET.S */
2536    /*
2537     * General 32-bit instance field get.
2538     *
2539     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2540     */
2541    /* op vA, vB, field@CCCC */
2542    mov     r0, rINST, lsr #12          @ r0<- B
2543    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2544    FETCH(r1, 1)                        @ r1<- field ref CCCC
2545    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2546    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2547    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2548    cmp     r0, #0                      @ is resolved entry null?
2549    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25508:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2551    EXPORT_PC()                         @ resolve() could throw
2552    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2553    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2554    cmp     r0, #0
2555    bne     .LOP_IGET_CHAR_finish
2556    b       common_exceptionThrown
2557
2558
2559/* ------------------------------ */
2560    .balign 64
2561.L_OP_IGET_SHORT: /* 0x58 */
2562/* File: armv5te/OP_IGET_SHORT.S */
2563@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2564/* File: armv5te/OP_IGET.S */
2565    /*
2566     * General 32-bit instance field get.
2567     *
2568     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2569     */
2570    /* op vA, vB, field@CCCC */
2571    mov     r0, rINST, lsr #12          @ r0<- B
2572    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2573    FETCH(r1, 1)                        @ r1<- field ref CCCC
2574    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2575    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2576    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2577    cmp     r0, #0                      @ is resolved entry null?
2578    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25798:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2580    EXPORT_PC()                         @ resolve() could throw
2581    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2582    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2583    cmp     r0, #0
2584    bne     .LOP_IGET_SHORT_finish
2585    b       common_exceptionThrown
2586
2587
2588/* ------------------------------ */
2589    .balign 64
2590.L_OP_IPUT: /* 0x59 */
2591/* File: armv6t2/OP_IPUT.S */
2592    /*
2593     * General 32-bit instance field put.
2594     *
2595     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2596     */
2597    /* op vA, vB, field@CCCC */
2598    mov     r0, rINST, lsr #12          @ r0<- B
2599    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2600    FETCH(r1, 1)                        @ r1<- field ref CCCC
2601    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2602    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2603    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2604    cmp     r0, #0                      @ is resolved entry null?
2605    bne     .LOP_IPUT_finish          @ no, already resolved
26068:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2607    EXPORT_PC()                         @ resolve() could throw
2608    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2609    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2610    cmp     r0, #0                      @ success?
2611    bne     .LOP_IPUT_finish          @ yes, finish up
2612    b       common_exceptionThrown
2613
2614/* ------------------------------ */
2615    .balign 64
2616.L_OP_IPUT_WIDE: /* 0x5a */
2617/* File: armv6t2/OP_IPUT_WIDE.S */
2618    /* iput-wide vA, vB, field@CCCC */
2619    mov     r0, rINST, lsr #12          @ r0<- B
2620    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2621    FETCH(r1, 1)                        @ r1<- field ref CCCC
2622    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2623    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2624    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2625    cmp     r0, #0                      @ is resolved entry null?
2626    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26278:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2628    EXPORT_PC()                         @ resolve() could throw
2629    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2630    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2631    cmp     r0, #0                      @ success?
2632    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2633    b       common_exceptionThrown
2634
2635/* ------------------------------ */
2636    .balign 64
2637.L_OP_IPUT_OBJECT: /* 0x5b */
2638/* File: armv5te/OP_IPUT_OBJECT.S */
2639/* File: armv5te/OP_IPUT.S */
2640    /*
2641     * General 32-bit instance field put.
2642     *
2643     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2644     */
2645    /* op vA, vB, field@CCCC */
2646    mov     r0, rINST, lsr #12          @ r0<- B
2647    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2648    FETCH(r1, 1)                        @ r1<- field ref CCCC
2649    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2650    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2651    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2652    cmp     r0, #0                      @ is resolved entry null?
2653    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26548:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2655    EXPORT_PC()                         @ resolve() could throw
2656    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2657    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2658    cmp     r0, #0                      @ success?
2659    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2660    b       common_exceptionThrown
2661
2662
2663/* ------------------------------ */
2664    .balign 64
2665.L_OP_IPUT_BOOLEAN: /* 0x5c */
2666/* File: armv5te/OP_IPUT_BOOLEAN.S */
2667@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2668/* File: armv5te/OP_IPUT.S */
2669    /*
2670     * General 32-bit instance field put.
2671     *
2672     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2673     */
2674    /* op vA, vB, field@CCCC */
2675    mov     r0, rINST, lsr #12          @ r0<- B
2676    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2677    FETCH(r1, 1)                        @ r1<- field ref CCCC
2678    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2679    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2680    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2681    cmp     r0, #0                      @ is resolved entry null?
2682    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26838:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2684    EXPORT_PC()                         @ resolve() could throw
2685    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2686    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2687    cmp     r0, #0                      @ success?
2688    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2689    b       common_exceptionThrown
2690
2691
2692/* ------------------------------ */
2693    .balign 64
2694.L_OP_IPUT_BYTE: /* 0x5d */
2695/* File: armv5te/OP_IPUT_BYTE.S */
2696@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2697/* File: armv5te/OP_IPUT.S */
2698    /*
2699     * General 32-bit instance field put.
2700     *
2701     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2702     */
2703    /* op vA, vB, field@CCCC */
2704    mov     r0, rINST, lsr #12          @ r0<- B
2705    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2706    FETCH(r1, 1)                        @ r1<- field ref CCCC
2707    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2708    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2709    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2710    cmp     r0, #0                      @ is resolved entry null?
2711    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27128:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2713    EXPORT_PC()                         @ resolve() could throw
2714    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2715    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2716    cmp     r0, #0                      @ success?
2717    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2718    b       common_exceptionThrown
2719
2720
2721/* ------------------------------ */
2722    .balign 64
2723.L_OP_IPUT_CHAR: /* 0x5e */
2724/* File: armv5te/OP_IPUT_CHAR.S */
2725@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2726/* File: armv5te/OP_IPUT.S */
2727    /*
2728     * General 32-bit instance field put.
2729     *
2730     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2731     */
2732    /* op vA, vB, field@CCCC */
2733    mov     r0, rINST, lsr #12          @ r0<- B
2734    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2735    FETCH(r1, 1)                        @ r1<- field ref CCCC
2736    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2737    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2738    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2739    cmp     r0, #0                      @ is resolved entry null?
2740    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27418:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2742    EXPORT_PC()                         @ resolve() could throw
2743    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2744    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2745    cmp     r0, #0                      @ success?
2746    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2747    b       common_exceptionThrown
2748
2749
2750/* ------------------------------ */
2751    .balign 64
2752.L_OP_IPUT_SHORT: /* 0x5f */
2753/* File: armv5te/OP_IPUT_SHORT.S */
2754@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2755/* File: armv5te/OP_IPUT.S */
2756    /*
2757     * General 32-bit instance field put.
2758     *
2759     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2760     */
2761    /* op vA, vB, field@CCCC */
2762    mov     r0, rINST, lsr #12          @ r0<- B
2763    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2764    FETCH(r1, 1)                        @ r1<- field ref CCCC
2765    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2766    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2767    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2768    cmp     r0, #0                      @ is resolved entry null?
2769    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27708:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2771    EXPORT_PC()                         @ resolve() could throw
2772    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2773    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2774    cmp     r0, #0                      @ success?
2775    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2776    b       common_exceptionThrown
2777
2778
2779/* ------------------------------ */
2780    .balign 64
2781.L_OP_SGET: /* 0x60 */
2782/* File: armv5te/OP_SGET.S */
2783    /*
2784     * General 32-bit SGET handler.
2785     *
2786     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2787     */
2788    /* op vAA, field@BBBB */
2789    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2790    FETCH(r1, 1)                        @ r1<- field ref BBBB
2791    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2792    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2793    cmp     r0, #0                      @ is resolved entry null?
2794    beq     .LOP_SGET_resolve         @ yes, do resolve
2795.LOP_SGET_finish: @ field ptr in r0
2796    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2797    @ no-op                             @ acquiring load
2798    mov     r2, rINST, lsr #8           @ r2<- AA
2799    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2800    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2802    GOTO_OPCODE(ip)                     @ jump to next instruction
2803
2804/* ------------------------------ */
2805    .balign 64
2806.L_OP_SGET_WIDE: /* 0x61 */
2807/* File: armv5te/OP_SGET_WIDE.S */
2808    /*
2809     * 64-bit SGET handler.
2810     */
2811    /* sget-wide vAA, field@BBBB */
2812    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2813    FETCH(r1, 1)                        @ r1<- field ref BBBB
2814    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2815    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2816    cmp     r0, #0                      @ is resolved entry null?
2817    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2818.LOP_SGET_WIDE_finish:
2819    mov     r9, rINST, lsr #8           @ r9<- AA
2820    .if 0
2821    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2822    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2823    .else
2824    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2825    .endif
2826    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2827    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2828    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2830    GOTO_OPCODE(ip)                     @ jump to next instruction
2831
2832/* ------------------------------ */
2833    .balign 64
2834.L_OP_SGET_OBJECT: /* 0x62 */
2835/* File: armv5te/OP_SGET_OBJECT.S */
2836/* File: armv5te/OP_SGET.S */
2837    /*
2838     * General 32-bit SGET handler.
2839     *
2840     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2841     */
2842    /* op vAA, field@BBBB */
2843    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2844    FETCH(r1, 1)                        @ r1<- field ref BBBB
2845    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2846    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2847    cmp     r0, #0                      @ is resolved entry null?
2848    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2849.LOP_SGET_OBJECT_finish: @ field ptr in r0
2850    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2851    @ no-op                             @ acquiring load
2852    mov     r2, rINST, lsr #8           @ r2<- AA
2853    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2854    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2856    GOTO_OPCODE(ip)                     @ jump to next instruction
2857
2858
2859/* ------------------------------ */
2860    .balign 64
2861.L_OP_SGET_BOOLEAN: /* 0x63 */
2862/* File: armv5te/OP_SGET_BOOLEAN.S */
2863/* File: armv5te/OP_SGET.S */
2864    /*
2865     * General 32-bit SGET handler.
2866     *
2867     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2868     */
2869    /* op vAA, field@BBBB */
2870    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2871    FETCH(r1, 1)                        @ r1<- field ref BBBB
2872    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2873    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2874    cmp     r0, #0                      @ is resolved entry null?
2875    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2876.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2877    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2878    @ no-op                             @ acquiring load
2879    mov     r2, rINST, lsr #8           @ r2<- AA
2880    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2881    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2882    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2883    GOTO_OPCODE(ip)                     @ jump to next instruction
2884
2885
2886/* ------------------------------ */
2887    .balign 64
2888.L_OP_SGET_BYTE: /* 0x64 */
2889/* File: armv5te/OP_SGET_BYTE.S */
2890/* File: armv5te/OP_SGET.S */
2891    /*
2892     * General 32-bit SGET handler.
2893     *
2894     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2895     */
2896    /* op vAA, field@BBBB */
2897    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2898    FETCH(r1, 1)                        @ r1<- field ref BBBB
2899    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2900    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2901    cmp     r0, #0                      @ is resolved entry null?
2902    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2903.LOP_SGET_BYTE_finish: @ field ptr in r0
2904    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2905    @ no-op                             @ acquiring load
2906    mov     r2, rINST, lsr #8           @ r2<- AA
2907    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2908    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2910    GOTO_OPCODE(ip)                     @ jump to next instruction
2911
2912
2913/* ------------------------------ */
2914    .balign 64
2915.L_OP_SGET_CHAR: /* 0x65 */
2916/* File: armv5te/OP_SGET_CHAR.S */
2917/* File: armv5te/OP_SGET.S */
2918    /*
2919     * General 32-bit SGET handler.
2920     *
2921     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2922     */
2923    /* op vAA, field@BBBB */
2924    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2925    FETCH(r1, 1)                        @ r1<- field ref BBBB
2926    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2927    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2928    cmp     r0, #0                      @ is resolved entry null?
2929    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2930.LOP_SGET_CHAR_finish: @ field ptr in r0
2931    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2932    @ no-op                             @ acquiring load
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_SHORT: /* 0x66 */
2943/* File: armv5te/OP_SGET_SHORT.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_SHORT_resolve         @ yes, do resolve
2957.LOP_SGET_SHORT_finish: @ field ptr in r0
2958    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2959    @ no-op                             @ acquiring load
2960    mov     r2, rINST, lsr #8           @ r2<- AA
2961    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2962    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2963    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2964    GOTO_OPCODE(ip)                     @ jump to next instruction
2965
2966
2967/* ------------------------------ */
2968    .balign 64
2969.L_OP_SPUT: /* 0x67 */
2970/* File: armv5te/OP_SPUT.S */
2971    /*
2972     * General 32-bit SPUT handler.
2973     *
2974     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-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_SPUT_resolve         @ yes, do resolve
2983.LOP_SPUT_finish:   @ field ptr in r0
2984    mov     r2, rINST, lsr #8           @ r2<- AA
2985    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2986    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2987    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2988    @ no-op                             @ releasing store
2989    str     r1, [r0, #offStaticField_value] @ field<- vAA
2990    GOTO_OPCODE(ip)                     @ jump to next instruction
2991
2992/* ------------------------------ */
2993    .balign 64
2994.L_OP_SPUT_WIDE: /* 0x68 */
2995/* File: armv5te/OP_SPUT_WIDE.S */
2996    /*
2997     * 64-bit SPUT handler.
2998     */
2999    /* sput-wide vAA, field@BBBB */
3000    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3001    FETCH(r1, 1)                        @ r1<- field ref BBBB
3002    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3003    mov     r9, rINST, lsr #8           @ r9<- AA
3004    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3005    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3006    cmp     r2, #0                      @ is resolved entry null?
3007    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3008.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3009    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3010    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3011    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3012    .if 0
3013    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3014    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3015    .else
3016    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3017    .endif
3018    GOTO_OPCODE(r10)                    @ jump to next instruction
3019
3020/* ------------------------------ */
3021    .balign 64
3022.L_OP_SPUT_OBJECT: /* 0x69 */
3023/* File: armv5te/OP_SPUT_OBJECT.S */
3024/* File: armv5te/OP_SPUT.S */
3025    /*
3026     * General 32-bit SPUT handler.
3027     *
3028     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3029     */
3030    /* op vAA, field@BBBB */
3031    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3032    FETCH(r1, 1)                        @ r1<- field ref BBBB
3033    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3034    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3035    cmp     r0, #0                      @ is resolved entry null?
3036    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3037.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3038    mov     r2, rINST, lsr #8           @ r2<- AA
3039    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3040    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3042    @ no-op                             @ releasing store
3043    str     r1, [r0, #offStaticField_value] @ field<- vAA
3044    GOTO_OPCODE(ip)                     @ jump to next instruction
3045
3046
3047/* ------------------------------ */
3048    .balign 64
3049.L_OP_SPUT_BOOLEAN: /* 0x6a */
3050/* File: armv5te/OP_SPUT_BOOLEAN.S */
3051/* File: armv5te/OP_SPUT.S */
3052    /*
3053     * General 32-bit SPUT handler.
3054     *
3055     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3056     */
3057    /* op vAA, field@BBBB */
3058    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3059    FETCH(r1, 1)                        @ r1<- field ref BBBB
3060    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3061    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3062    cmp     r0, #0                      @ is resolved entry null?
3063    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3064.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3065    mov     r2, rINST, lsr #8           @ r2<- AA
3066    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3067    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3068    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3069    @ no-op                             @ releasing store
3070    str     r1, [r0, #offStaticField_value] @ field<- vAA
3071    GOTO_OPCODE(ip)                     @ jump to next instruction
3072
3073
3074/* ------------------------------ */
3075    .balign 64
3076.L_OP_SPUT_BYTE: /* 0x6b */
3077/* File: armv5te/OP_SPUT_BYTE.S */
3078/* File: armv5te/OP_SPUT.S */
3079    /*
3080     * General 32-bit SPUT handler.
3081     *
3082     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3083     */
3084    /* op vAA, field@BBBB */
3085    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3086    FETCH(r1, 1)                        @ r1<- field ref BBBB
3087    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3088    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3089    cmp     r0, #0                      @ is resolved entry null?
3090    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3091.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3092    mov     r2, rINST, lsr #8           @ r2<- AA
3093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3094    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3096    @ no-op                             @ releasing store
3097    str     r1, [r0, #offStaticField_value] @ field<- vAA
3098    GOTO_OPCODE(ip)                     @ jump to next instruction
3099
3100
3101/* ------------------------------ */
3102    .balign 64
3103.L_OP_SPUT_CHAR: /* 0x6c */
3104/* File: armv5te/OP_SPUT_CHAR.S */
3105/* File: armv5te/OP_SPUT.S */
3106    /*
3107     * General 32-bit SPUT handler.
3108     *
3109     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3110     */
3111    /* op vAA, field@BBBB */
3112    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3113    FETCH(r1, 1)                        @ r1<- field ref BBBB
3114    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3115    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3116    cmp     r0, #0                      @ is resolved entry null?
3117    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3118.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3119    mov     r2, rINST, lsr #8           @ r2<- AA
3120    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3121    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3122    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3123    @ no-op                             @ releasing store
3124    str     r1, [r0, #offStaticField_value] @ field<- vAA
3125    GOTO_OPCODE(ip)                     @ jump to next instruction
3126
3127
3128/* ------------------------------ */
3129    .balign 64
3130.L_OP_SPUT_SHORT: /* 0x6d */
3131/* File: armv5te/OP_SPUT_SHORT.S */
3132/* File: armv5te/OP_SPUT.S */
3133    /*
3134     * General 32-bit SPUT handler.
3135     *
3136     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3137     */
3138    /* op vAA, field@BBBB */
3139    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3140    FETCH(r1, 1)                        @ r1<- field ref BBBB
3141    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3142    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3143    cmp     r0, #0                      @ is resolved entry null?
3144    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3145.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3146    mov     r2, rINST, lsr #8           @ r2<- AA
3147    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3148    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3149    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3150    @ no-op                             @ releasing store
3151    str     r1, [r0, #offStaticField_value] @ field<- vAA
3152    GOTO_OPCODE(ip)                     @ jump to next instruction
3153
3154
3155/* ------------------------------ */
3156    .balign 64
3157.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3158/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3159    /*
3160     * Handle a virtual method call.
3161     *
3162     * for: invoke-virtual, invoke-virtual/range
3163     */
3164    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3165    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3166    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3167    FETCH(r1, 1)                        @ r1<- BBBB
3168    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3169    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3170    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3171    .if     (!0)
3172    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3173    .endif
3174    cmp     r0, #0                      @ already resolved?
3175    EXPORT_PC()                         @ must export for invoke
3176    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3177    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3178    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3179    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3180    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3181    cmp     r0, #0                      @ got null?
3182    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3183    b       common_exceptionThrown      @ yes, handle exception
3184
3185/* ------------------------------ */
3186    .balign 64
3187.L_OP_INVOKE_SUPER: /* 0x6f */
3188/* File: armv5te/OP_INVOKE_SUPER.S */
3189    /*
3190     * Handle a "super" method call.
3191     *
3192     * for: invoke-super, invoke-super/range
3193     */
3194    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3195    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3196    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3197    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3198    .if     (!0)
3199    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3200    .endif
3201    FETCH(r1, 1)                        @ r1<- BBBB
3202    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3203    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3204    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3205    cmp     r2, #0                      @ null "this"?
3206    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3207    beq     common_errNullObject        @ null "this", throw exception
3208    cmp     r0, #0                      @ already resolved?
3209    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3210    EXPORT_PC()                         @ must export for invoke
3211    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3212    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3213
3214/* ------------------------------ */
3215    .balign 64
3216.L_OP_INVOKE_DIRECT: /* 0x70 */
3217/* File: armv5te/OP_INVOKE_DIRECT.S */
3218    /*
3219     * Handle a direct method call.
3220     *
3221     * (We could defer the "is 'this' pointer null" test to the common
3222     * method invocation code, and use a flag to indicate that static
3223     * calls don't count.  If we do this as part of copying the arguments
3224     * out we could avoiding loading the first arg twice.)
3225     *
3226     * for: invoke-direct, invoke-direct/range
3227     */
3228    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3229    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3230    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3231    FETCH(r1, 1)                        @ r1<- BBBB
3232    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3233    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3234    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3235    .if     (!0)
3236    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3237    .endif
3238    cmp     r0, #0                      @ already resolved?
3239    EXPORT_PC()                         @ must export for invoke
3240    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3241    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3242.LOP_INVOKE_DIRECT_finish:
3243    cmp     r2, #0                      @ null "this" ref?
3244    bne     common_invokeMethodNoRange   @ no, continue on
3245    b       common_errNullObject        @ yes, throw exception
3246
3247/* ------------------------------ */
3248    .balign 64
3249.L_OP_INVOKE_STATIC: /* 0x71 */
3250/* File: armv5te/OP_INVOKE_STATIC.S */
3251    /*
3252     * Handle a static method call.
3253     *
3254     * for: invoke-static, invoke-static/range
3255     */
3256    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3257    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3258    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3259    FETCH(r1, 1)                        @ r1<- BBBB
3260    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3261    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3262    cmp     r0, #0                      @ already resolved?
3263    EXPORT_PC()                         @ must export for invoke
3264    bne     common_invokeMethodNoRange @ yes, continue on
32650:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3266    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3267    mov     r2, #METHOD_STATIC          @ resolver method type
3268    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3269    cmp     r0, #0                      @ got null?
3270    bne     common_invokeMethodNoRange @ no, continue
3271    b       common_exceptionThrown      @ yes, handle exception
3272
3273/* ------------------------------ */
3274    .balign 64
3275.L_OP_INVOKE_INTERFACE: /* 0x72 */
3276/* File: armv5te/OP_INVOKE_INTERFACE.S */
3277    /*
3278     * Handle an interface method call.
3279     *
3280     * for: invoke-interface, invoke-interface/range
3281     */
3282    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3283    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3284    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3285    FETCH(r1, 1)                        @ r1<- BBBB
3286    .if     (!0)
3287    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3288    .endif
3289    EXPORT_PC()                         @ must export for invoke
3290    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3291    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3292    cmp     r0, #0                      @ null obj?
3293    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3294    beq     common_errNullObject        @ yes, fail
3295    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3296    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3297    cmp     r0, #0                      @ failed?
3298    beq     common_exceptionThrown      @ yes, handle exception
3299    b       common_invokeMethodNoRange @ jump to common handler
3300
3301/* ------------------------------ */
3302    .balign 64
3303.L_OP_UNUSED_73: /* 0x73 */
3304/* File: armv5te/OP_UNUSED_73.S */
3305/* File: armv5te/unused.S */
3306    bl      common_abort
3307
3308
3309/* ------------------------------ */
3310    .balign 64
3311.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3312/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3313/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3314    /*
3315     * Handle a virtual method call.
3316     *
3317     * for: invoke-virtual, invoke-virtual/range
3318     */
3319    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3320    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3321    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3322    FETCH(r1, 1)                        @ r1<- BBBB
3323    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3324    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3325    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3326    .if     (!1)
3327    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3328    .endif
3329    cmp     r0, #0                      @ already resolved?
3330    EXPORT_PC()                         @ must export for invoke
3331    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3332    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3333    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3334    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3335    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3336    cmp     r0, #0                      @ got null?
3337    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3338    b       common_exceptionThrown      @ yes, handle exception
3339
3340
3341/* ------------------------------ */
3342    .balign 64
3343.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3344/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3345/* File: armv5te/OP_INVOKE_SUPER.S */
3346    /*
3347     * Handle a "super" method call.
3348     *
3349     * for: invoke-super, invoke-super/range
3350     */
3351    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3352    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3353    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3354    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3355    .if     (!1)
3356    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3357    .endif
3358    FETCH(r1, 1)                        @ r1<- BBBB
3359    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3360    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3361    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3362    cmp     r2, #0                      @ null "this"?
3363    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3364    beq     common_errNullObject        @ null "this", throw exception
3365    cmp     r0, #0                      @ already resolved?
3366    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3367    EXPORT_PC()                         @ must export for invoke
3368    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3369    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3370
3371
3372/* ------------------------------ */
3373    .balign 64
3374.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3375/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3376/* File: armv5te/OP_INVOKE_DIRECT.S */
3377    /*
3378     * Handle a direct method call.
3379     *
3380     * (We could defer the "is 'this' pointer null" test to the common
3381     * method invocation code, and use a flag to indicate that static
3382     * calls don't count.  If we do this as part of copying the arguments
3383     * out we could avoiding loading the first arg twice.)
3384     *
3385     * for: invoke-direct, invoke-direct/range
3386     */
3387    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3388    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3389    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3390    FETCH(r1, 1)                        @ r1<- BBBB
3391    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3392    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3393    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3394    .if     (!1)
3395    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3396    .endif
3397    cmp     r0, #0                      @ already resolved?
3398    EXPORT_PC()                         @ must export for invoke
3399    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3400    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3401.LOP_INVOKE_DIRECT_RANGE_finish:
3402    cmp     r2, #0                      @ null "this" ref?
3403    bne     common_invokeMethodRange   @ no, continue on
3404    b       common_errNullObject        @ yes, throw exception
3405
3406
3407/* ------------------------------ */
3408    .balign 64
3409.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3410/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3411/* File: armv5te/OP_INVOKE_STATIC.S */
3412    /*
3413     * Handle a static method call.
3414     *
3415     * for: invoke-static, invoke-static/range
3416     */
3417    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3418    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3419    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3420    FETCH(r1, 1)                        @ r1<- BBBB
3421    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3422    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3423    cmp     r0, #0                      @ already resolved?
3424    EXPORT_PC()                         @ must export for invoke
3425    bne     common_invokeMethodRange @ yes, continue on
34260:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3427    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3428    mov     r2, #METHOD_STATIC          @ resolver method type
3429    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3430    cmp     r0, #0                      @ got null?
3431    bne     common_invokeMethodRange @ no, continue
3432    b       common_exceptionThrown      @ yes, handle exception
3433
3434
3435/* ------------------------------ */
3436    .balign 64
3437.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3438/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3439/* File: armv5te/OP_INVOKE_INTERFACE.S */
3440    /*
3441     * Handle an interface method call.
3442     *
3443     * for: invoke-interface, invoke-interface/range
3444     */
3445    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3446    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3447    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3448    FETCH(r1, 1)                        @ r1<- BBBB
3449    .if     (!1)
3450    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3451    .endif
3452    EXPORT_PC()                         @ must export for invoke
3453    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3454    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3455    cmp     r0, #0                      @ null obj?
3456    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3457    beq     common_errNullObject        @ yes, fail
3458    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3459    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3460    cmp     r0, #0                      @ failed?
3461    beq     common_exceptionThrown      @ yes, handle exception
3462    b       common_invokeMethodRange @ jump to common handler
3463
3464
3465/* ------------------------------ */
3466    .balign 64
3467.L_OP_UNUSED_79: /* 0x79 */
3468/* File: armv5te/OP_UNUSED_79.S */
3469/* File: armv5te/unused.S */
3470    bl      common_abort
3471
3472
3473/* ------------------------------ */
3474    .balign 64
3475.L_OP_UNUSED_7A: /* 0x7a */
3476/* File: armv5te/OP_UNUSED_7A.S */
3477/* File: armv5te/unused.S */
3478    bl      common_abort
3479
3480
3481/* ------------------------------ */
3482    .balign 64
3483.L_OP_NEG_INT: /* 0x7b */
3484/* File: armv6t2/OP_NEG_INT.S */
3485/* File: armv6t2/unop.S */
3486    /*
3487     * Generic 32-bit unary operation.  Provide an "instr" line that
3488     * specifies an instruction that performs "result = op r0".
3489     * This could be an ARM instruction or a function call.
3490     *
3491     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3492     *      int-to-byte, int-to-char, int-to-short
3493     */
3494    /* unop vA, vB */
3495    mov     r3, rINST, lsr #12          @ r3<- B
3496    ubfx    r9, rINST, #8, #4           @ r9<- A
3497    GET_VREG(r0, r3)                    @ r0<- vB
3498                               @ optional op; may set condition codes
3499    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3500    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3501    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3502    SET_VREG(r0, r9)                    @ vAA<- r0
3503    GOTO_OPCODE(ip)                     @ jump to next instruction
3504    /* 8-9 instructions */
3505
3506
3507/* ------------------------------ */
3508    .balign 64
3509.L_OP_NOT_INT: /* 0x7c */
3510/* File: armv6t2/OP_NOT_INT.S */
3511/* File: armv6t2/unop.S */
3512    /*
3513     * Generic 32-bit unary operation.  Provide an "instr" line that
3514     * specifies an instruction that performs "result = op r0".
3515     * This could be an ARM instruction or a function call.
3516     *
3517     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3518     *      int-to-byte, int-to-char, int-to-short
3519     */
3520    /* unop vA, vB */
3521    mov     r3, rINST, lsr #12          @ r3<- B
3522    ubfx    r9, rINST, #8, #4           @ r9<- A
3523    GET_VREG(r0, r3)                    @ r0<- vB
3524                               @ optional op; may set condition codes
3525    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3526    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3527    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3528    SET_VREG(r0, r9)                    @ vAA<- r0
3529    GOTO_OPCODE(ip)                     @ jump to next instruction
3530    /* 8-9 instructions */
3531
3532
3533/* ------------------------------ */
3534    .balign 64
3535.L_OP_NEG_LONG: /* 0x7d */
3536/* File: armv6t2/OP_NEG_LONG.S */
3537/* File: armv6t2/unopWide.S */
3538    /*
3539     * Generic 64-bit unary operation.  Provide an "instr" line that
3540     * specifies an instruction that performs "result = op r0/r1".
3541     * This could be an ARM instruction or a function call.
3542     *
3543     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3544     */
3545    /* unop vA, vB */
3546    mov     r3, rINST, lsr #12          @ r3<- B
3547    ubfx    r9, rINST, #8, #4           @ r9<- A
3548    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3549    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3550    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3551    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3552    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3553    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3554    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3555    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3556    GOTO_OPCODE(ip)                     @ jump to next instruction
3557    /* 10-11 instructions */
3558
3559
3560/* ------------------------------ */
3561    .balign 64
3562.L_OP_NOT_LONG: /* 0x7e */
3563/* File: armv6t2/OP_NOT_LONG.S */
3564/* File: armv6t2/unopWide.S */
3565    /*
3566     * Generic 64-bit unary operation.  Provide an "instr" line that
3567     * specifies an instruction that performs "result = op r0/r1".
3568     * This could be an ARM instruction or a function call.
3569     *
3570     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3571     */
3572    /* unop vA, vB */
3573    mov     r3, rINST, lsr #12          @ r3<- B
3574    ubfx    r9, rINST, #8, #4           @ r9<- A
3575    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3576    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3577    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3578    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3579    mvn     r0, r0                           @ optional op; may set condition codes
3580    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3582    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3583    GOTO_OPCODE(ip)                     @ jump to next instruction
3584    /* 10-11 instructions */
3585
3586
3587/* ------------------------------ */
3588    .balign 64
3589.L_OP_NEG_FLOAT: /* 0x7f */
3590/* File: armv6t2/OP_NEG_FLOAT.S */
3591/* File: armv6t2/unop.S */
3592    /*
3593     * Generic 32-bit unary operation.  Provide an "instr" line that
3594     * specifies an instruction that performs "result = op r0".
3595     * This could be an ARM instruction or a function call.
3596     *
3597     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3598     *      int-to-byte, int-to-char, int-to-short
3599     */
3600    /* unop vA, vB */
3601    mov     r3, rINST, lsr #12          @ r3<- B
3602    ubfx    r9, rINST, #8, #4           @ r9<- A
3603    GET_VREG(r0, r3)                    @ r0<- vB
3604                               @ optional op; may set condition codes
3605    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3606    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3608    SET_VREG(r0, r9)                    @ vAA<- r0
3609    GOTO_OPCODE(ip)                     @ jump to next instruction
3610    /* 8-9 instructions */
3611
3612
3613/* ------------------------------ */
3614    .balign 64
3615.L_OP_NEG_DOUBLE: /* 0x80 */
3616/* File: armv6t2/OP_NEG_DOUBLE.S */
3617/* File: armv6t2/unopWide.S */
3618    /*
3619     * Generic 64-bit unary operation.  Provide an "instr" line that
3620     * specifies an instruction that performs "result = op r0/r1".
3621     * This could be an ARM instruction or a function call.
3622     *
3623     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3624     */
3625    /* unop vA, vB */
3626    mov     r3, rINST, lsr #12          @ r3<- B
3627    ubfx    r9, rINST, #8, #4           @ r9<- A
3628    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3629    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3630    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3631    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3632                               @ optional op; may set condition codes
3633    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3634    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3635    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3636    GOTO_OPCODE(ip)                     @ jump to next instruction
3637    /* 10-11 instructions */
3638
3639
3640/* ------------------------------ */
3641    .balign 64
3642.L_OP_INT_TO_LONG: /* 0x81 */
3643/* File: armv6t2/OP_INT_TO_LONG.S */
3644/* File: armv6t2/unopWider.S */
3645    /*
3646     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3647     * that specifies an instruction that performs "result = op r0", where
3648     * "result" is a 64-bit quantity in r0/r1.
3649     *
3650     * For: int-to-long, int-to-double, float-to-long, float-to-double
3651     */
3652    /* unop vA, vB */
3653    mov     r3, rINST, lsr #12          @ r3<- B
3654    ubfx    r9, rINST, #8, #4           @ r9<- A
3655    GET_VREG(r0, r3)                    @ r0<- vB
3656    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3657                               @ optional op; may set condition codes
3658    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3659    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3660    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3661    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3662    GOTO_OPCODE(ip)                     @ jump to next instruction
3663    /* 9-10 instructions */
3664
3665
3666/* ------------------------------ */
3667    .balign 64
3668.L_OP_INT_TO_FLOAT: /* 0x82 */
3669/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3670/* File: arm-vfp/funop.S */
3671    /*
3672     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3673     * line that specifies an instruction that performs "s1 = op s0".
3674     *
3675     * for: int-to-float, float-to-int
3676     */
3677    /* unop vA, vB */
3678    mov     r3, rINST, lsr #12          @ r3<- B
3679    mov     r9, rINST, lsr #8           @ r9<- A+
3680    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3681    flds    s0, [r3]                    @ s0<- vB
3682    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3683    and     r9, r9, #15                 @ r9<- A
3684    fsitos  s1, s0                              @ s1<- op
3685    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3686    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3687    fsts    s1, [r9]                    @ vA<- s1
3688    GOTO_OPCODE(ip)                     @ jump to next instruction
3689
3690
3691/* ------------------------------ */
3692    .balign 64
3693.L_OP_INT_TO_DOUBLE: /* 0x83 */
3694/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3695/* File: arm-vfp/funopWider.S */
3696    /*
3697     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3698     * "instr" line that specifies an instruction that performs "d0 = op s0".
3699     *
3700     * For: int-to-double, float-to-double
3701     */
3702    /* unop vA, vB */
3703    mov     r3, rINST, lsr #12          @ r3<- B
3704    mov     r9, rINST, lsr #8           @ r9<- A+
3705    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3706    flds    s0, [r3]                    @ s0<- vB
3707    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3708    and     r9, r9, #15                 @ r9<- A
3709    fsitod  d0, s0                              @ d0<- op
3710    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3711    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3712    fstd    d0, [r9]                    @ vA<- d0
3713    GOTO_OPCODE(ip)                     @ jump to next instruction
3714
3715
3716/* ------------------------------ */
3717    .balign 64
3718.L_OP_LONG_TO_INT: /* 0x84 */
3719/* File: armv5te/OP_LONG_TO_INT.S */
3720/* we ignore the high word, making this equivalent to a 32-bit reg move */
3721/* File: armv5te/OP_MOVE.S */
3722    /* for move, move-object, long-to-int */
3723    /* op vA, vB */
3724    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3725    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3726    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3727    GET_VREG(r2, r1)                    @ r2<- fp[B]
3728    and     r0, r0, #15
3729    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3730    SET_VREG(r2, r0)                    @ fp[A]<- r2
3731    GOTO_OPCODE(ip)                     @ execute next instruction
3732
3733
3734/* ------------------------------ */
3735    .balign 64
3736.L_OP_LONG_TO_FLOAT: /* 0x85 */
3737/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3738/* File: armv6t2/unopNarrower.S */
3739    /*
3740     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3741     * that specifies an instruction that performs "result = op r0/r1", where
3742     * "result" is a 32-bit quantity in r0.
3743     *
3744     * For: long-to-float, double-to-int, double-to-float
3745     *
3746     * (This would work for long-to-int, but that instruction is actually
3747     * an exact match for OP_MOVE.)
3748     */
3749    /* unop vA, vB */
3750    mov     r3, rINST, lsr #12          @ r3<- B
3751    ubfx    r9, rINST, #8, #4           @ r9<- A
3752    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3753    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3754    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3755                               @ optional op; may set condition codes
3756    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3758    SET_VREG(r0, r9)                    @ vA<- r0
3759    GOTO_OPCODE(ip)                     @ jump to next instruction
3760    /* 9-10 instructions */
3761
3762
3763/* ------------------------------ */
3764    .balign 64
3765.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3766/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3767/* File: armv6t2/unopWide.S */
3768    /*
3769     * Generic 64-bit unary operation.  Provide an "instr" line that
3770     * specifies an instruction that performs "result = op r0/r1".
3771     * This could be an ARM instruction or a function call.
3772     *
3773     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3774     */
3775    /* unop vA, vB */
3776    mov     r3, rINST, lsr #12          @ r3<- B
3777    ubfx    r9, rINST, #8, #4           @ r9<- A
3778    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3779    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3780    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3781    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3782                               @ optional op; may set condition codes
3783    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3784    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3785    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3786    GOTO_OPCODE(ip)                     @ jump to next instruction
3787    /* 10-11 instructions */
3788
3789
3790/* ------------------------------ */
3791    .balign 64
3792.L_OP_FLOAT_TO_INT: /* 0x87 */
3793/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3794/* File: arm-vfp/funop.S */
3795    /*
3796     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3797     * line that specifies an instruction that performs "s1 = op s0".
3798     *
3799     * for: int-to-float, float-to-int
3800     */
3801    /* unop vA, vB */
3802    mov     r3, rINST, lsr #12          @ r3<- B
3803    mov     r9, rINST, lsr #8           @ r9<- A+
3804    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3805    flds    s0, [r3]                    @ s0<- vB
3806    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3807    and     r9, r9, #15                 @ r9<- A
3808    ftosizs s1, s0                              @ s1<- op
3809    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3810    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3811    fsts    s1, [r9]                    @ vA<- s1
3812    GOTO_OPCODE(ip)                     @ jump to next instruction
3813
3814
3815/* ------------------------------ */
3816    .balign 64
3817.L_OP_FLOAT_TO_LONG: /* 0x88 */
3818/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3819@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3820/* File: armv6t2/unopWider.S */
3821    /*
3822     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3823     * that specifies an instruction that performs "result = op r0", where
3824     * "result" is a 64-bit quantity in r0/r1.
3825     *
3826     * For: int-to-long, int-to-double, float-to-long, float-to-double
3827     */
3828    /* unop vA, vB */
3829    mov     r3, rINST, lsr #12          @ r3<- B
3830    ubfx    r9, rINST, #8, #4           @ r9<- A
3831    GET_VREG(r0, r3)                    @ r0<- vB
3832    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3833                               @ optional op; may set condition codes
3834    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3835    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3837    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3838    GOTO_OPCODE(ip)                     @ jump to next instruction
3839    /* 9-10 instructions */
3840
3841
3842
3843/* ------------------------------ */
3844    .balign 64
3845.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3846/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3847/* File: arm-vfp/funopWider.S */
3848    /*
3849     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3850     * "instr" line that specifies an instruction that performs "d0 = op s0".
3851     *
3852     * For: int-to-double, float-to-double
3853     */
3854    /* unop vA, vB */
3855    mov     r3, rINST, lsr #12          @ r3<- B
3856    mov     r9, rINST, lsr #8           @ r9<- A+
3857    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3858    flds    s0, [r3]                    @ s0<- vB
3859    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3860    and     r9, r9, #15                 @ r9<- A
3861    fcvtds  d0, s0                              @ d0<- op
3862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3863    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3864    fstd    d0, [r9]                    @ vA<- d0
3865    GOTO_OPCODE(ip)                     @ jump to next instruction
3866
3867
3868/* ------------------------------ */
3869    .balign 64
3870.L_OP_DOUBLE_TO_INT: /* 0x8a */
3871/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3872/* File: arm-vfp/funopNarrower.S */
3873    /*
3874     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3875     * "instr" line that specifies an instruction that performs "s0 = op d0".
3876     *
3877     * For: double-to-int, double-to-float
3878     */
3879    /* unop vA, vB */
3880    mov     r3, rINST, lsr #12          @ r3<- B
3881    mov     r9, rINST, lsr #8           @ r9<- A+
3882    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3883    fldd    d0, [r3]                    @ d0<- vB
3884    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3885    and     r9, r9, #15                 @ r9<- A
3886    ftosizd  s0, d0                              @ s0<- op
3887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3888    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3889    fsts    s0, [r9]                    @ vA<- s0
3890    GOTO_OPCODE(ip)                     @ jump to next instruction
3891
3892
3893/* ------------------------------ */
3894    .balign 64
3895.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3896/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3897@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3898/* File: armv6t2/unopWide.S */
3899    /*
3900     * Generic 64-bit unary operation.  Provide an "instr" line that
3901     * specifies an instruction that performs "result = op r0/r1".
3902     * This could be an ARM instruction or a function call.
3903     *
3904     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3905     */
3906    /* unop vA, vB */
3907    mov     r3, rINST, lsr #12          @ r3<- B
3908    ubfx    r9, rINST, #8, #4           @ r9<- A
3909    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3910    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3911    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3912    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3913                               @ optional op; may set condition codes
3914    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3916    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3917    GOTO_OPCODE(ip)                     @ jump to next instruction
3918    /* 10-11 instructions */
3919
3920
3921
3922/* ------------------------------ */
3923    .balign 64
3924.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3925/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3926/* File: arm-vfp/funopNarrower.S */
3927    /*
3928     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3929     * "instr" line that specifies an instruction that performs "s0 = op d0".
3930     *
3931     * For: double-to-int, double-to-float
3932     */
3933    /* unop vA, vB */
3934    mov     r3, rINST, lsr #12          @ r3<- B
3935    mov     r9, rINST, lsr #8           @ r9<- A+
3936    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3937    fldd    d0, [r3]                    @ d0<- vB
3938    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3939    and     r9, r9, #15                 @ r9<- A
3940    fcvtsd  s0, d0                              @ s0<- op
3941    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3942    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3943    fsts    s0, [r9]                    @ vA<- s0
3944    GOTO_OPCODE(ip)                     @ jump to next instruction
3945
3946
3947/* ------------------------------ */
3948    .balign 64
3949.L_OP_INT_TO_BYTE: /* 0x8d */
3950/* File: armv6t2/OP_INT_TO_BYTE.S */
3951/* File: armv6t2/unop.S */
3952    /*
3953     * Generic 32-bit unary operation.  Provide an "instr" line that
3954     * specifies an instruction that performs "result = op r0".
3955     * This could be an ARM instruction or a function call.
3956     *
3957     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3958     *      int-to-byte, int-to-char, int-to-short
3959     */
3960    /* unop vA, vB */
3961    mov     r3, rINST, lsr #12          @ r3<- B
3962    ubfx    r9, rINST, #8, #4           @ r9<- A
3963    GET_VREG(r0, r3)                    @ r0<- vB
3964                               @ optional op; may set condition codes
3965    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3966    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3968    SET_VREG(r0, r9)                    @ vAA<- r0
3969    GOTO_OPCODE(ip)                     @ jump to next instruction
3970    /* 8-9 instructions */
3971
3972
3973/* ------------------------------ */
3974    .balign 64
3975.L_OP_INT_TO_CHAR: /* 0x8e */
3976/* File: armv6t2/OP_INT_TO_CHAR.S */
3977/* File: armv6t2/unop.S */
3978    /*
3979     * Generic 32-bit unary operation.  Provide an "instr" line that
3980     * specifies an instruction that performs "result = op r0".
3981     * This could be an ARM instruction or a function call.
3982     *
3983     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3984     *      int-to-byte, int-to-char, int-to-short
3985     */
3986    /* unop vA, vB */
3987    mov     r3, rINST, lsr #12          @ r3<- B
3988    ubfx    r9, rINST, #8, #4           @ r9<- A
3989    GET_VREG(r0, r3)                    @ r0<- vB
3990                               @ optional op; may set condition codes
3991    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3992    uxth    r0, r0                              @ r0<- op, r0-r3 changed
3993    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3994    SET_VREG(r0, r9)                    @ vAA<- r0
3995    GOTO_OPCODE(ip)                     @ jump to next instruction
3996    /* 8-9 instructions */
3997
3998
3999/* ------------------------------ */
4000    .balign 64
4001.L_OP_INT_TO_SHORT: /* 0x8f */
4002/* File: armv6t2/OP_INT_TO_SHORT.S */
4003/* File: armv6t2/unop.S */
4004    /*
4005     * Generic 32-bit unary operation.  Provide an "instr" line that
4006     * specifies an instruction that performs "result = op r0".
4007     * This could be an ARM instruction or a function call.
4008     *
4009     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4010     *      int-to-byte, int-to-char, int-to-short
4011     */
4012    /* unop vA, vB */
4013    mov     r3, rINST, lsr #12          @ r3<- B
4014    ubfx    r9, rINST, #8, #4           @ r9<- A
4015    GET_VREG(r0, r3)                    @ r0<- vB
4016                               @ optional op; may set condition codes
4017    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4018    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4019    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4020    SET_VREG(r0, r9)                    @ vAA<- r0
4021    GOTO_OPCODE(ip)                     @ jump to next instruction
4022    /* 8-9 instructions */
4023
4024
4025/* ------------------------------ */
4026    .balign 64
4027.L_OP_ADD_INT: /* 0x90 */
4028/* File: armv5te/OP_ADD_INT.S */
4029/* File: armv5te/binop.S */
4030    /*
4031     * Generic 32-bit binary operation.  Provide an "instr" line that
4032     * specifies an instruction that performs "result = r0 op r1".
4033     * This could be an ARM instruction or a function call.  (If the result
4034     * comes back in a register other than r0, you can override "result".)
4035     *
4036     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4037     * vCC (r1).  Useful for integer division and modulus.  Note that we
4038     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4039     * handles it correctly.
4040     *
4041     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4042     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4043     *      mul-float, div-float, rem-float
4044     */
4045    /* binop vAA, vBB, vCC */
4046    FETCH(r0, 1)                        @ r0<- CCBB
4047    mov     r9, rINST, lsr #8           @ r9<- AA
4048    mov     r3, r0, lsr #8              @ r3<- CC
4049    and     r2, r0, #255                @ r2<- BB
4050    GET_VREG(r1, r3)                    @ r1<- vCC
4051    GET_VREG(r0, r2)                    @ r0<- vBB
4052    .if 0
4053    cmp     r1, #0                      @ is second operand zero?
4054    beq     common_errDivideByZero
4055    .endif
4056
4057    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4058                               @ optional op; may set condition codes
4059    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4060    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4061    SET_VREG(r0, r9)               @ vAA<- r0
4062    GOTO_OPCODE(ip)                     @ jump to next instruction
4063    /* 11-14 instructions */
4064
4065
4066/* ------------------------------ */
4067    .balign 64
4068.L_OP_SUB_INT: /* 0x91 */
4069/* File: armv5te/OP_SUB_INT.S */
4070/* File: armv5te/binop.S */
4071    /*
4072     * Generic 32-bit binary operation.  Provide an "instr" line that
4073     * specifies an instruction that performs "result = r0 op r1".
4074     * This could be an ARM instruction or a function call.  (If the result
4075     * comes back in a register other than r0, you can override "result".)
4076     *
4077     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4078     * vCC (r1).  Useful for integer division and modulus.  Note that we
4079     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4080     * handles it correctly.
4081     *
4082     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4083     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4084     *      mul-float, div-float, rem-float
4085     */
4086    /* binop vAA, vBB, vCC */
4087    FETCH(r0, 1)                        @ r0<- CCBB
4088    mov     r9, rINST, lsr #8           @ r9<- AA
4089    mov     r3, r0, lsr #8              @ r3<- CC
4090    and     r2, r0, #255                @ r2<- BB
4091    GET_VREG(r1, r3)                    @ r1<- vCC
4092    GET_VREG(r0, r2)                    @ r0<- vBB
4093    .if 0
4094    cmp     r1, #0                      @ is second operand zero?
4095    beq     common_errDivideByZero
4096    .endif
4097
4098    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4099                               @ optional op; may set condition codes
4100    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4102    SET_VREG(r0, r9)               @ vAA<- r0
4103    GOTO_OPCODE(ip)                     @ jump to next instruction
4104    /* 11-14 instructions */
4105
4106
4107/* ------------------------------ */
4108    .balign 64
4109.L_OP_MUL_INT: /* 0x92 */
4110/* File: armv5te/OP_MUL_INT.S */
4111/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4112/* File: armv5te/binop.S */
4113    /*
4114     * Generic 32-bit binary operation.  Provide an "instr" line that
4115     * specifies an instruction that performs "result = r0 op r1".
4116     * This could be an ARM instruction or a function call.  (If the result
4117     * comes back in a register other than r0, you can override "result".)
4118     *
4119     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4120     * vCC (r1).  Useful for integer division and modulus.  Note that we
4121     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4122     * handles it correctly.
4123     *
4124     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4125     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4126     *      mul-float, div-float, rem-float
4127     */
4128    /* binop vAA, vBB, vCC */
4129    FETCH(r0, 1)                        @ r0<- CCBB
4130    mov     r9, rINST, lsr #8           @ r9<- AA
4131    mov     r3, r0, lsr #8              @ r3<- CC
4132    and     r2, r0, #255                @ r2<- BB
4133    GET_VREG(r1, r3)                    @ r1<- vCC
4134    GET_VREG(r0, r2)                    @ r0<- vBB
4135    .if 0
4136    cmp     r1, #0                      @ is second operand zero?
4137    beq     common_errDivideByZero
4138    .endif
4139
4140    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4141                               @ optional op; may set condition codes
4142    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4144    SET_VREG(r0, r9)               @ vAA<- r0
4145    GOTO_OPCODE(ip)                     @ jump to next instruction
4146    /* 11-14 instructions */
4147
4148
4149/* ------------------------------ */
4150    .balign 64
4151.L_OP_DIV_INT: /* 0x93 */
4152/* File: armv5te/OP_DIV_INT.S */
4153/* File: armv5te/binop.S */
4154    /*
4155     * Generic 32-bit binary operation.  Provide an "instr" line that
4156     * specifies an instruction that performs "result = r0 op r1".
4157     * This could be an ARM instruction or a function call.  (If the result
4158     * comes back in a register other than r0, you can override "result".)
4159     *
4160     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4161     * vCC (r1).  Useful for integer division and modulus.  Note that we
4162     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4163     * handles it correctly.
4164     *
4165     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4166     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4167     *      mul-float, div-float, rem-float
4168     */
4169    /* binop vAA, vBB, vCC */
4170    FETCH(r0, 1)                        @ r0<- CCBB
4171    mov     r9, rINST, lsr #8           @ r9<- AA
4172    mov     r3, r0, lsr #8              @ r3<- CC
4173    and     r2, r0, #255                @ r2<- BB
4174    GET_VREG(r1, r3)                    @ r1<- vCC
4175    GET_VREG(r0, r2)                    @ r0<- vBB
4176    .if 1
4177    cmp     r1, #0                      @ is second operand zero?
4178    beq     common_errDivideByZero
4179    .endif
4180
4181    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4182                               @ optional op; may set condition codes
4183    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4185    SET_VREG(r0, r9)               @ vAA<- r0
4186    GOTO_OPCODE(ip)                     @ jump to next instruction
4187    /* 11-14 instructions */
4188
4189
4190/* ------------------------------ */
4191    .balign 64
4192.L_OP_REM_INT: /* 0x94 */
4193/* File: armv5te/OP_REM_INT.S */
4194/* idivmod returns quotient in r0 and remainder in r1 */
4195/* File: armv5te/binop.S */
4196    /*
4197     * Generic 32-bit binary operation.  Provide an "instr" line that
4198     * specifies an instruction that performs "result = r0 op r1".
4199     * This could be an ARM instruction or a function call.  (If the result
4200     * comes back in a register other than r0, you can override "result".)
4201     *
4202     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4203     * vCC (r1).  Useful for integer division and modulus.  Note that we
4204     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4205     * handles it correctly.
4206     *
4207     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4208     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4209     *      mul-float, div-float, rem-float
4210     */
4211    /* binop vAA, vBB, vCC */
4212    FETCH(r0, 1)                        @ r0<- CCBB
4213    mov     r9, rINST, lsr #8           @ r9<- AA
4214    mov     r3, r0, lsr #8              @ r3<- CC
4215    and     r2, r0, #255                @ r2<- BB
4216    GET_VREG(r1, r3)                    @ r1<- vCC
4217    GET_VREG(r0, r2)                    @ r0<- vBB
4218    .if 1
4219    cmp     r1, #0                      @ is second operand zero?
4220    beq     common_errDivideByZero
4221    .endif
4222
4223    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4224                               @ optional op; may set condition codes
4225    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4226    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4227    SET_VREG(r1, r9)               @ vAA<- r1
4228    GOTO_OPCODE(ip)                     @ jump to next instruction
4229    /* 11-14 instructions */
4230
4231
4232/* ------------------------------ */
4233    .balign 64
4234.L_OP_AND_INT: /* 0x95 */
4235/* File: armv5te/OP_AND_INT.S */
4236/* File: armv5te/binop.S */
4237    /*
4238     * Generic 32-bit binary operation.  Provide an "instr" line that
4239     * specifies an instruction that performs "result = r0 op r1".
4240     * This could be an ARM instruction or a function call.  (If the result
4241     * comes back in a register other than r0, you can override "result".)
4242     *
4243     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4244     * vCC (r1).  Useful for integer division and modulus.  Note that we
4245     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4246     * handles it correctly.
4247     *
4248     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4249     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4250     *      mul-float, div-float, rem-float
4251     */
4252    /* binop vAA, vBB, vCC */
4253    FETCH(r0, 1)                        @ r0<- CCBB
4254    mov     r9, rINST, lsr #8           @ r9<- AA
4255    mov     r3, r0, lsr #8              @ r3<- CC
4256    and     r2, r0, #255                @ r2<- BB
4257    GET_VREG(r1, r3)                    @ r1<- vCC
4258    GET_VREG(r0, r2)                    @ r0<- vBB
4259    .if 0
4260    cmp     r1, #0                      @ is second operand zero?
4261    beq     common_errDivideByZero
4262    .endif
4263
4264    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4265                               @ optional op; may set condition codes
4266    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4267    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4268    SET_VREG(r0, r9)               @ vAA<- r0
4269    GOTO_OPCODE(ip)                     @ jump to next instruction
4270    /* 11-14 instructions */
4271
4272
4273/* ------------------------------ */
4274    .balign 64
4275.L_OP_OR_INT: /* 0x96 */
4276/* File: armv5te/OP_OR_INT.S */
4277/* File: armv5te/binop.S */
4278    /*
4279     * Generic 32-bit binary operation.  Provide an "instr" line that
4280     * specifies an instruction that performs "result = r0 op r1".
4281     * This could be an ARM instruction or a function call.  (If the result
4282     * comes back in a register other than r0, you can override "result".)
4283     *
4284     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4285     * vCC (r1).  Useful for integer division and modulus.  Note that we
4286     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4287     * handles it correctly.
4288     *
4289     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4290     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4291     *      mul-float, div-float, rem-float
4292     */
4293    /* binop vAA, vBB, vCC */
4294    FETCH(r0, 1)                        @ r0<- CCBB
4295    mov     r9, rINST, lsr #8           @ r9<- AA
4296    mov     r3, r0, lsr #8              @ r3<- CC
4297    and     r2, r0, #255                @ r2<- BB
4298    GET_VREG(r1, r3)                    @ r1<- vCC
4299    GET_VREG(r0, r2)                    @ r0<- vBB
4300    .if 0
4301    cmp     r1, #0                      @ is second operand zero?
4302    beq     common_errDivideByZero
4303    .endif
4304
4305    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4306                               @ optional op; may set condition codes
4307    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4309    SET_VREG(r0, r9)               @ vAA<- r0
4310    GOTO_OPCODE(ip)                     @ jump to next instruction
4311    /* 11-14 instructions */
4312
4313
4314/* ------------------------------ */
4315    .balign 64
4316.L_OP_XOR_INT: /* 0x97 */
4317/* File: armv5te/OP_XOR_INT.S */
4318/* File: armv5te/binop.S */
4319    /*
4320     * Generic 32-bit binary operation.  Provide an "instr" line that
4321     * specifies an instruction that performs "result = r0 op r1".
4322     * This could be an ARM instruction or a function call.  (If the result
4323     * comes back in a register other than r0, you can override "result".)
4324     *
4325     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4326     * vCC (r1).  Useful for integer division and modulus.  Note that we
4327     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4328     * handles it correctly.
4329     *
4330     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4331     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4332     *      mul-float, div-float, rem-float
4333     */
4334    /* binop vAA, vBB, vCC */
4335    FETCH(r0, 1)                        @ r0<- CCBB
4336    mov     r9, rINST, lsr #8           @ r9<- AA
4337    mov     r3, r0, lsr #8              @ r3<- CC
4338    and     r2, r0, #255                @ r2<- BB
4339    GET_VREG(r1, r3)                    @ r1<- vCC
4340    GET_VREG(r0, r2)                    @ r0<- vBB
4341    .if 0
4342    cmp     r1, #0                      @ is second operand zero?
4343    beq     common_errDivideByZero
4344    .endif
4345
4346    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4347                               @ optional op; may set condition codes
4348    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4350    SET_VREG(r0, r9)               @ vAA<- r0
4351    GOTO_OPCODE(ip)                     @ jump to next instruction
4352    /* 11-14 instructions */
4353
4354
4355/* ------------------------------ */
4356    .balign 64
4357.L_OP_SHL_INT: /* 0x98 */
4358/* File: armv5te/OP_SHL_INT.S */
4359/* File: armv5te/binop.S */
4360    /*
4361     * Generic 32-bit binary operation.  Provide an "instr" line that
4362     * specifies an instruction that performs "result = r0 op r1".
4363     * This could be an ARM instruction or a function call.  (If the result
4364     * comes back in a register other than r0, you can override "result".)
4365     *
4366     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4367     * vCC (r1).  Useful for integer division and modulus.  Note that we
4368     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4369     * handles it correctly.
4370     *
4371     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4372     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4373     *      mul-float, div-float, rem-float
4374     */
4375    /* binop vAA, vBB, vCC */
4376    FETCH(r0, 1)                        @ r0<- CCBB
4377    mov     r9, rINST, lsr #8           @ r9<- AA
4378    mov     r3, r0, lsr #8              @ r3<- CC
4379    and     r2, r0, #255                @ r2<- BB
4380    GET_VREG(r1, r3)                    @ r1<- vCC
4381    GET_VREG(r0, r2)                    @ r0<- vBB
4382    .if 0
4383    cmp     r1, #0                      @ is second operand zero?
4384    beq     common_errDivideByZero
4385    .endif
4386
4387    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4388    and     r1, r1, #31                           @ optional op; may set condition codes
4389    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4391    SET_VREG(r0, r9)               @ vAA<- r0
4392    GOTO_OPCODE(ip)                     @ jump to next instruction
4393    /* 11-14 instructions */
4394
4395
4396/* ------------------------------ */
4397    .balign 64
4398.L_OP_SHR_INT: /* 0x99 */
4399/* File: armv5te/OP_SHR_INT.S */
4400/* File: armv5te/binop.S */
4401    /*
4402     * Generic 32-bit binary operation.  Provide an "instr" line that
4403     * specifies an instruction that performs "result = r0 op r1".
4404     * This could be an ARM instruction or a function call.  (If the result
4405     * comes back in a register other than r0, you can override "result".)
4406     *
4407     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4408     * vCC (r1).  Useful for integer division and modulus.  Note that we
4409     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4410     * handles it correctly.
4411     *
4412     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4413     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4414     *      mul-float, div-float, rem-float
4415     */
4416    /* binop vAA, vBB, vCC */
4417    FETCH(r0, 1)                        @ r0<- CCBB
4418    mov     r9, rINST, lsr #8           @ r9<- AA
4419    mov     r3, r0, lsr #8              @ r3<- CC
4420    and     r2, r0, #255                @ r2<- BB
4421    GET_VREG(r1, r3)                    @ r1<- vCC
4422    GET_VREG(r0, r2)                    @ r0<- vBB
4423    .if 0
4424    cmp     r1, #0                      @ is second operand zero?
4425    beq     common_errDivideByZero
4426    .endif
4427
4428    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4429    and     r1, r1, #31                           @ optional op; may set condition codes
4430    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4432    SET_VREG(r0, r9)               @ vAA<- r0
4433    GOTO_OPCODE(ip)                     @ jump to next instruction
4434    /* 11-14 instructions */
4435
4436
4437/* ------------------------------ */
4438    .balign 64
4439.L_OP_USHR_INT: /* 0x9a */
4440/* File: armv5te/OP_USHR_INT.S */
4441/* File: armv5te/binop.S */
4442    /*
4443     * Generic 32-bit binary operation.  Provide an "instr" line that
4444     * specifies an instruction that performs "result = r0 op r1".
4445     * This could be an ARM instruction or a function call.  (If the result
4446     * comes back in a register other than r0, you can override "result".)
4447     *
4448     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4449     * vCC (r1).  Useful for integer division and modulus.  Note that we
4450     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4451     * handles it correctly.
4452     *
4453     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4454     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4455     *      mul-float, div-float, rem-float
4456     */
4457    /* binop vAA, vBB, vCC */
4458    FETCH(r0, 1)                        @ r0<- CCBB
4459    mov     r9, rINST, lsr #8           @ r9<- AA
4460    mov     r3, r0, lsr #8              @ r3<- CC
4461    and     r2, r0, #255                @ r2<- BB
4462    GET_VREG(r1, r3)                    @ r1<- vCC
4463    GET_VREG(r0, r2)                    @ r0<- vBB
4464    .if 0
4465    cmp     r1, #0                      @ is second operand zero?
4466    beq     common_errDivideByZero
4467    .endif
4468
4469    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4470    and     r1, r1, #31                           @ optional op; may set condition codes
4471    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4472    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4473    SET_VREG(r0, r9)               @ vAA<- r0
4474    GOTO_OPCODE(ip)                     @ jump to next instruction
4475    /* 11-14 instructions */
4476
4477
4478/* ------------------------------ */
4479    .balign 64
4480.L_OP_ADD_LONG: /* 0x9b */
4481/* File: armv5te/OP_ADD_LONG.S */
4482/* File: armv5te/binopWide.S */
4483    /*
4484     * Generic 64-bit binary operation.  Provide an "instr" line that
4485     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4486     * This could be an ARM instruction or a function call.  (If the result
4487     * comes back in a register other than r0, you can override "result".)
4488     *
4489     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4490     * vCC (r1).  Useful for integer division and modulus.
4491     *
4492     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4493     *      xor-long, add-double, sub-double, mul-double, div-double,
4494     *      rem-double
4495     *
4496     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4497     */
4498    /* binop vAA, vBB, vCC */
4499    FETCH(r0, 1)                        @ r0<- CCBB
4500    mov     r9, rINST, lsr #8           @ r9<- AA
4501    and     r2, r0, #255                @ r2<- BB
4502    mov     r3, r0, lsr #8              @ r3<- CC
4503    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4504    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4505    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4506    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4507    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4508    .if 0
4509    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4510    beq     common_errDivideByZero
4511    .endif
4512    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4513
4514    adds    r0, r0, r2                           @ optional op; may set condition codes
4515    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4517    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4518    GOTO_OPCODE(ip)                     @ jump to next instruction
4519    /* 14-17 instructions */
4520
4521
4522/* ------------------------------ */
4523    .balign 64
4524.L_OP_SUB_LONG: /* 0x9c */
4525/* File: armv5te/OP_SUB_LONG.S */
4526/* File: armv5te/binopWide.S */
4527    /*
4528     * Generic 64-bit binary operation.  Provide an "instr" line that
4529     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4530     * This could be an ARM instruction or a function call.  (If the result
4531     * comes back in a register other than r0, you can override "result".)
4532     *
4533     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4534     * vCC (r1).  Useful for integer division and modulus.
4535     *
4536     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4537     *      xor-long, add-double, sub-double, mul-double, div-double,
4538     *      rem-double
4539     *
4540     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4541     */
4542    /* binop vAA, vBB, vCC */
4543    FETCH(r0, 1)                        @ r0<- CCBB
4544    mov     r9, rINST, lsr #8           @ r9<- AA
4545    and     r2, r0, #255                @ r2<- BB
4546    mov     r3, r0, lsr #8              @ r3<- CC
4547    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4548    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4549    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4550    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4551    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4552    .if 0
4553    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4554    beq     common_errDivideByZero
4555    .endif
4556    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4557
4558    subs    r0, r0, r2                           @ optional op; may set condition codes
4559    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4560    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4561    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4562    GOTO_OPCODE(ip)                     @ jump to next instruction
4563    /* 14-17 instructions */
4564
4565
4566/* ------------------------------ */
4567    .balign 64
4568.L_OP_MUL_LONG: /* 0x9d */
4569/* File: armv5te/OP_MUL_LONG.S */
4570    /*
4571     * Signed 64-bit integer multiply.
4572     *
4573     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4574     *        WX
4575     *      x YZ
4576     *  --------
4577     *     ZW ZX
4578     *  YW YX
4579     *
4580     * The low word of the result holds ZX, the high word holds
4581     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4582     * it doesn't fit in the low 64 bits.
4583     *
4584     * Unlike most ARM math operations, multiply instructions have
4585     * restrictions on using the same register more than once (Rd and Rm
4586     * cannot be the same).
4587     */
4588    /* mul-long vAA, vBB, vCC */
4589    FETCH(r0, 1)                        @ r0<- CCBB
4590    and     r2, r0, #255                @ r2<- BB
4591    mov     r3, r0, lsr #8              @ r3<- CC
4592    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4593    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4594    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4595    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4596    mul     ip, r2, r1                  @  ip<- ZxW
4597    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4598    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4599    mov     r0, rINST, lsr #8           @ r0<- AA
4600    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4601    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4602    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4603    b       .LOP_MUL_LONG_finish
4604
4605/* ------------------------------ */
4606    .balign 64
4607.L_OP_DIV_LONG: /* 0x9e */
4608/* File: armv5te/OP_DIV_LONG.S */
4609/* File: armv5te/binopWide.S */
4610    /*
4611     * Generic 64-bit binary operation.  Provide an "instr" line that
4612     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4613     * This could be an ARM instruction or a function call.  (If the result
4614     * comes back in a register other than r0, you can override "result".)
4615     *
4616     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4617     * vCC (r1).  Useful for integer division and modulus.
4618     *
4619     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4620     *      xor-long, add-double, sub-double, mul-double, div-double,
4621     *      rem-double
4622     *
4623     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4624     */
4625    /* binop vAA, vBB, vCC */
4626    FETCH(r0, 1)                        @ r0<- CCBB
4627    mov     r9, rINST, lsr #8           @ r9<- AA
4628    and     r2, r0, #255                @ r2<- BB
4629    mov     r3, r0, lsr #8              @ r3<- CC
4630    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4631    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4632    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4633    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4634    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4635    .if 1
4636    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4637    beq     common_errDivideByZero
4638    .endif
4639    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4640
4641                               @ optional op; may set condition codes
4642    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4643    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4644    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4645    GOTO_OPCODE(ip)                     @ jump to next instruction
4646    /* 14-17 instructions */
4647
4648
4649/* ------------------------------ */
4650    .balign 64
4651.L_OP_REM_LONG: /* 0x9f */
4652/* File: armv5te/OP_REM_LONG.S */
4653/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4654/* File: armv5te/binopWide.S */
4655    /*
4656     * Generic 64-bit binary operation.  Provide an "instr" line that
4657     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4658     * This could be an ARM instruction or a function call.  (If the result
4659     * comes back in a register other than r0, you can override "result".)
4660     *
4661     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4662     * vCC (r1).  Useful for integer division and modulus.
4663     *
4664     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4665     *      xor-long, add-double, sub-double, mul-double, div-double,
4666     *      rem-double
4667     *
4668     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4669     */
4670    /* binop vAA, vBB, vCC */
4671    FETCH(r0, 1)                        @ r0<- CCBB
4672    mov     r9, rINST, lsr #8           @ r9<- AA
4673    and     r2, r0, #255                @ r2<- BB
4674    mov     r3, r0, lsr #8              @ r3<- CC
4675    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4676    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4677    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4678    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4679    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4680    .if 1
4681    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4682    beq     common_errDivideByZero
4683    .endif
4684    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4685
4686                               @ optional op; may set condition codes
4687    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4689    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4690    GOTO_OPCODE(ip)                     @ jump to next instruction
4691    /* 14-17 instructions */
4692
4693
4694/* ------------------------------ */
4695    .balign 64
4696.L_OP_AND_LONG: /* 0xa0 */
4697/* File: armv5te/OP_AND_LONG.S */
4698/* File: armv5te/binopWide.S */
4699    /*
4700     * Generic 64-bit binary operation.  Provide an "instr" line that
4701     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4702     * This could be an ARM instruction or a function call.  (If the result
4703     * comes back in a register other than r0, you can override "result".)
4704     *
4705     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4706     * vCC (r1).  Useful for integer division and modulus.
4707     *
4708     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4709     *      xor-long, add-double, sub-double, mul-double, div-double,
4710     *      rem-double
4711     *
4712     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4713     */
4714    /* binop vAA, vBB, vCC */
4715    FETCH(r0, 1)                        @ r0<- CCBB
4716    mov     r9, rINST, lsr #8           @ r9<- AA
4717    and     r2, r0, #255                @ r2<- BB
4718    mov     r3, r0, lsr #8              @ r3<- CC
4719    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4720    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4721    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4722    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4723    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4724    .if 0
4725    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4726    beq     common_errDivideByZero
4727    .endif
4728    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4729
4730    and     r0, r0, r2                           @ optional op; may set condition codes
4731    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4733    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4734    GOTO_OPCODE(ip)                     @ jump to next instruction
4735    /* 14-17 instructions */
4736
4737
4738/* ------------------------------ */
4739    .balign 64
4740.L_OP_OR_LONG: /* 0xa1 */
4741/* File: armv5te/OP_OR_LONG.S */
4742/* File: armv5te/binopWide.S */
4743    /*
4744     * Generic 64-bit binary operation.  Provide an "instr" line that
4745     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4746     * This could be an ARM instruction or a function call.  (If the result
4747     * comes back in a register other than r0, you can override "result".)
4748     *
4749     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4750     * vCC (r1).  Useful for integer division and modulus.
4751     *
4752     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4753     *      xor-long, add-double, sub-double, mul-double, div-double,
4754     *      rem-double
4755     *
4756     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4757     */
4758    /* binop vAA, vBB, vCC */
4759    FETCH(r0, 1)                        @ r0<- CCBB
4760    mov     r9, rINST, lsr #8           @ r9<- AA
4761    and     r2, r0, #255                @ r2<- BB
4762    mov     r3, r0, lsr #8              @ r3<- CC
4763    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4764    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4765    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4766    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4767    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4768    .if 0
4769    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4770    beq     common_errDivideByZero
4771    .endif
4772    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4773
4774    orr     r0, r0, r2                           @ optional op; may set condition codes
4775    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4777    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4778    GOTO_OPCODE(ip)                     @ jump to next instruction
4779    /* 14-17 instructions */
4780
4781
4782/* ------------------------------ */
4783    .balign 64
4784.L_OP_XOR_LONG: /* 0xa2 */
4785/* File: armv5te/OP_XOR_LONG.S */
4786/* File: armv5te/binopWide.S */
4787    /*
4788     * Generic 64-bit binary operation.  Provide an "instr" line that
4789     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4790     * This could be an ARM instruction or a function call.  (If the result
4791     * comes back in a register other than r0, you can override "result".)
4792     *
4793     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4794     * vCC (r1).  Useful for integer division and modulus.
4795     *
4796     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4797     *      xor-long, add-double, sub-double, mul-double, div-double,
4798     *      rem-double
4799     *
4800     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4801     */
4802    /* binop vAA, vBB, vCC */
4803    FETCH(r0, 1)                        @ r0<- CCBB
4804    mov     r9, rINST, lsr #8           @ r9<- AA
4805    and     r2, r0, #255                @ r2<- BB
4806    mov     r3, r0, lsr #8              @ r3<- CC
4807    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4808    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4809    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4810    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4811    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4812    .if 0
4813    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4814    beq     common_errDivideByZero
4815    .endif
4816    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4817
4818    eor     r0, r0, r2                           @ optional op; may set condition codes
4819    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4820    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4821    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4822    GOTO_OPCODE(ip)                     @ jump to next instruction
4823    /* 14-17 instructions */
4824
4825
4826/* ------------------------------ */
4827    .balign 64
4828.L_OP_SHL_LONG: /* 0xa3 */
4829/* File: armv5te/OP_SHL_LONG.S */
4830    /*
4831     * Long integer shift.  This is different from the generic 32/64-bit
4832     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4833     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4834     * 6 bits of the shift distance.
4835     */
4836    /* shl-long vAA, vBB, vCC */
4837    FETCH(r0, 1)                        @ r0<- CCBB
4838    mov     r9, rINST, lsr #8           @ r9<- AA
4839    and     r3, r0, #255                @ r3<- BB
4840    mov     r0, r0, lsr #8              @ r0<- CC
4841    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4842    GET_VREG(r2, r0)                    @ r2<- vCC
4843    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4844    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4845    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4846
4847    mov     r1, r1, asl r2              @  r1<- r1 << r2
4848    rsb     r3, r2, #32                 @  r3<- 32 - r2
4849    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4850    subs    ip, r2, #32                 @  ip<- r2 - 32
4851    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4852    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4853    b       .LOP_SHL_LONG_finish
4854
4855/* ------------------------------ */
4856    .balign 64
4857.L_OP_SHR_LONG: /* 0xa4 */
4858/* File: armv5te/OP_SHR_LONG.S */
4859    /*
4860     * Long integer shift.  This is different from the generic 32/64-bit
4861     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4862     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4863     * 6 bits of the shift distance.
4864     */
4865    /* shr-long vAA, vBB, vCC */
4866    FETCH(r0, 1)                        @ r0<- CCBB
4867    mov     r9, rINST, lsr #8           @ r9<- AA
4868    and     r3, r0, #255                @ r3<- BB
4869    mov     r0, r0, lsr #8              @ r0<- CC
4870    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4871    GET_VREG(r2, r0)                    @ r2<- vCC
4872    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4873    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4874    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4875
4876    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4877    rsb     r3, r2, #32                 @  r3<- 32 - r2
4878    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4879    subs    ip, r2, #32                 @  ip<- r2 - 32
4880    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4881    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4882    b       .LOP_SHR_LONG_finish
4883
4884/* ------------------------------ */
4885    .balign 64
4886.L_OP_USHR_LONG: /* 0xa5 */
4887/* File: armv5te/OP_USHR_LONG.S */
4888    /*
4889     * Long integer shift.  This is different from the generic 32/64-bit
4890     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4891     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4892     * 6 bits of the shift distance.
4893     */
4894    /* ushr-long vAA, vBB, vCC */
4895    FETCH(r0, 1)                        @ r0<- CCBB
4896    mov     r9, rINST, lsr #8           @ r9<- AA
4897    and     r3, r0, #255                @ r3<- BB
4898    mov     r0, r0, lsr #8              @ r0<- CC
4899    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4900    GET_VREG(r2, r0)                    @ r2<- vCC
4901    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4902    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4903    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4904
4905    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4906    rsb     r3, r2, #32                 @  r3<- 32 - r2
4907    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4908    subs    ip, r2, #32                 @  ip<- r2 - 32
4909    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4910    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4911    b       .LOP_USHR_LONG_finish
4912
4913/* ------------------------------ */
4914    .balign 64
4915.L_OP_ADD_FLOAT: /* 0xa6 */
4916/* File: arm-vfp/OP_ADD_FLOAT.S */
4917/* File: arm-vfp/fbinop.S */
4918    /*
4919     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4920     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4921     * use the "softfp" ABI, this must be an instruction, not a function call.
4922     *
4923     * For: add-float, sub-float, mul-float, div-float
4924     */
4925    /* floatop vAA, vBB, vCC */
4926    FETCH(r0, 1)                        @ r0<- CCBB
4927    mov     r9, rINST, lsr #8           @ r9<- AA
4928    mov     r3, r0, lsr #8              @ r3<- CC
4929    and     r2, r0, #255                @ r2<- BB
4930    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4931    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4932    flds    s1, [r3]                    @ s1<- vCC
4933    flds    s0, [r2]                    @ s0<- vBB
4934
4935    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4936    fadds   s2, s0, s1                              @ s2<- op
4937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4938    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4939    fsts    s2, [r9]                    @ vAA<- s2
4940    GOTO_OPCODE(ip)                     @ jump to next instruction
4941
4942
4943/* ------------------------------ */
4944    .balign 64
4945.L_OP_SUB_FLOAT: /* 0xa7 */
4946/* File: arm-vfp/OP_SUB_FLOAT.S */
4947/* File: arm-vfp/fbinop.S */
4948    /*
4949     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4950     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4951     * use the "softfp" ABI, this must be an instruction, not a function call.
4952     *
4953     * For: add-float, sub-float, mul-float, div-float
4954     */
4955    /* floatop vAA, vBB, vCC */
4956    FETCH(r0, 1)                        @ r0<- CCBB
4957    mov     r9, rINST, lsr #8           @ r9<- AA
4958    mov     r3, r0, lsr #8              @ r3<- CC
4959    and     r2, r0, #255                @ r2<- BB
4960    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4961    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4962    flds    s1, [r3]                    @ s1<- vCC
4963    flds    s0, [r2]                    @ s0<- vBB
4964
4965    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4966    fsubs   s2, s0, s1                              @ s2<- op
4967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4968    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4969    fsts    s2, [r9]                    @ vAA<- s2
4970    GOTO_OPCODE(ip)                     @ jump to next instruction
4971
4972
4973/* ------------------------------ */
4974    .balign 64
4975.L_OP_MUL_FLOAT: /* 0xa8 */
4976/* File: arm-vfp/OP_MUL_FLOAT.S */
4977/* File: arm-vfp/fbinop.S */
4978    /*
4979     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4980     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4981     * use the "softfp" ABI, this must be an instruction, not a function call.
4982     *
4983     * For: add-float, sub-float, mul-float, div-float
4984     */
4985    /* floatop vAA, vBB, vCC */
4986    FETCH(r0, 1)                        @ r0<- CCBB
4987    mov     r9, rINST, lsr #8           @ r9<- AA
4988    mov     r3, r0, lsr #8              @ r3<- CC
4989    and     r2, r0, #255                @ r2<- BB
4990    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4991    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4992    flds    s1, [r3]                    @ s1<- vCC
4993    flds    s0, [r2]                    @ s0<- vBB
4994
4995    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4996    fmuls   s2, s0, s1                              @ s2<- op
4997    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4998    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4999    fsts    s2, [r9]                    @ vAA<- s2
5000    GOTO_OPCODE(ip)                     @ jump to next instruction
5001
5002
5003/* ------------------------------ */
5004    .balign 64
5005.L_OP_DIV_FLOAT: /* 0xa9 */
5006/* File: arm-vfp/OP_DIV_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    fdivs   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_REM_FLOAT: /* 0xaa */
5036/* File: armv5te/OP_REM_FLOAT.S */
5037/* EABI doesn't define a float remainder function, but libm does */
5038/* File: armv5te/binop.S */
5039    /*
5040     * Generic 32-bit binary operation.  Provide an "instr" line that
5041     * specifies an instruction that performs "result = r0 op r1".
5042     * This could be an ARM instruction or a function call.  (If the result
5043     * comes back in a register other than r0, you can override "result".)
5044     *
5045     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5046     * vCC (r1).  Useful for integer division and modulus.  Note that we
5047     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5048     * handles it correctly.
5049     *
5050     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5051     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5052     *      mul-float, div-float, rem-float
5053     */
5054    /* binop vAA, vBB, vCC */
5055    FETCH(r0, 1)                        @ r0<- CCBB
5056    mov     r9, rINST, lsr #8           @ r9<- AA
5057    mov     r3, r0, lsr #8              @ r3<- CC
5058    and     r2, r0, #255                @ r2<- BB
5059    GET_VREG(r1, r3)                    @ r1<- vCC
5060    GET_VREG(r0, r2)                    @ r0<- vBB
5061    .if 0
5062    cmp     r1, #0                      @ is second operand zero?
5063    beq     common_errDivideByZero
5064    .endif
5065
5066    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5067                               @ optional op; may set condition codes
5068    bl      fmodf                              @ r0<- op, r0-r3 changed
5069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5070    SET_VREG(r0, r9)               @ vAA<- r0
5071    GOTO_OPCODE(ip)                     @ jump to next instruction
5072    /* 11-14 instructions */
5073
5074
5075/* ------------------------------ */
5076    .balign 64
5077.L_OP_ADD_DOUBLE: /* 0xab */
5078/* File: arm-vfp/OP_ADD_DOUBLE.S */
5079/* File: arm-vfp/fbinopWide.S */
5080    /*
5081     * Generic 64-bit double-precision floating point binary operation.
5082     * Provide an "instr" line that specifies an instruction that performs
5083     * "d2 = d0 op d1".
5084     *
5085     * for: add-double, sub-double, mul-double, div-double
5086     */
5087    /* doubleop vAA, vBB, vCC */
5088    FETCH(r0, 1)                        @ r0<- CCBB
5089    mov     r9, rINST, lsr #8           @ r9<- AA
5090    mov     r3, r0, lsr #8              @ r3<- CC
5091    and     r2, r0, #255                @ r2<- BB
5092    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5093    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5094    fldd    d1, [r3]                    @ d1<- vCC
5095    fldd    d0, [r2]                    @ d0<- vBB
5096
5097    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5098    faddd   d2, d0, d1                              @ s2<- op
5099    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5100    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5101    fstd    d2, [r9]                    @ vAA<- d2
5102    GOTO_OPCODE(ip)                     @ jump to next instruction
5103
5104
5105/* ------------------------------ */
5106    .balign 64
5107.L_OP_SUB_DOUBLE: /* 0xac */
5108/* File: arm-vfp/OP_SUB_DOUBLE.S */
5109/* File: arm-vfp/fbinopWide.S */
5110    /*
5111     * Generic 64-bit double-precision floating point binary operation.
5112     * Provide an "instr" line that specifies an instruction that performs
5113     * "d2 = d0 op d1".
5114     *
5115     * for: add-double, sub-double, mul-double, div-double
5116     */
5117    /* doubleop vAA, vBB, vCC */
5118    FETCH(r0, 1)                        @ r0<- CCBB
5119    mov     r9, rINST, lsr #8           @ r9<- AA
5120    mov     r3, r0, lsr #8              @ r3<- CC
5121    and     r2, r0, #255                @ r2<- BB
5122    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5123    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5124    fldd    d1, [r3]                    @ d1<- vCC
5125    fldd    d0, [r2]                    @ d0<- vBB
5126
5127    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5128    fsubd   d2, d0, d1                              @ s2<- op
5129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5130    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5131    fstd    d2, [r9]                    @ vAA<- d2
5132    GOTO_OPCODE(ip)                     @ jump to next instruction
5133
5134
5135/* ------------------------------ */
5136    .balign 64
5137.L_OP_MUL_DOUBLE: /* 0xad */
5138/* File: arm-vfp/OP_MUL_DOUBLE.S */
5139/* File: arm-vfp/fbinopWide.S */
5140    /*
5141     * Generic 64-bit double-precision floating point binary operation.
5142     * Provide an "instr" line that specifies an instruction that performs
5143     * "d2 = d0 op d1".
5144     *
5145     * for: add-double, sub-double, mul-double, div-double
5146     */
5147    /* doubleop vAA, vBB, vCC */
5148    FETCH(r0, 1)                        @ r0<- CCBB
5149    mov     r9, rINST, lsr #8           @ r9<- AA
5150    mov     r3, r0, lsr #8              @ r3<- CC
5151    and     r2, r0, #255                @ r2<- BB
5152    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5153    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5154    fldd    d1, [r3]                    @ d1<- vCC
5155    fldd    d0, [r2]                    @ d0<- vBB
5156
5157    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5158    fmuld   d2, d0, d1                              @ s2<- op
5159    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5160    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5161    fstd    d2, [r9]                    @ vAA<- d2
5162    GOTO_OPCODE(ip)                     @ jump to next instruction
5163
5164
5165/* ------------------------------ */
5166    .balign 64
5167.L_OP_DIV_DOUBLE: /* 0xae */
5168/* File: arm-vfp/OP_DIV_DOUBLE.S */
5169/* File: arm-vfp/fbinopWide.S */
5170    /*
5171     * Generic 64-bit double-precision floating point binary operation.
5172     * Provide an "instr" line that specifies an instruction that performs
5173     * "d2 = d0 op d1".
5174     *
5175     * for: add-double, sub-double, mul-double, div-double
5176     */
5177    /* doubleop vAA, vBB, vCC */
5178    FETCH(r0, 1)                        @ r0<- CCBB
5179    mov     r9, rINST, lsr #8           @ r9<- AA
5180    mov     r3, r0, lsr #8              @ r3<- CC
5181    and     r2, r0, #255                @ r2<- BB
5182    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5183    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5184    fldd    d1, [r3]                    @ d1<- vCC
5185    fldd    d0, [r2]                    @ d0<- vBB
5186
5187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5188    fdivd   d2, d0, d1                              @ s2<- op
5189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5190    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5191    fstd    d2, [r9]                    @ vAA<- d2
5192    GOTO_OPCODE(ip)                     @ jump to next instruction
5193
5194
5195/* ------------------------------ */
5196    .balign 64
5197.L_OP_REM_DOUBLE: /* 0xaf */
5198/* File: armv5te/OP_REM_DOUBLE.S */
5199/* EABI doesn't define a double remainder function, but libm does */
5200/* File: armv5te/binopWide.S */
5201    /*
5202     * Generic 64-bit binary operation.  Provide an "instr" line that
5203     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5204     * This could be an ARM instruction or a function call.  (If the result
5205     * comes back in a register other than r0, you can override "result".)
5206     *
5207     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5208     * vCC (r1).  Useful for integer division and modulus.
5209     *
5210     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5211     *      xor-long, add-double, sub-double, mul-double, div-double,
5212     *      rem-double
5213     *
5214     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5215     */
5216    /* binop vAA, vBB, vCC */
5217    FETCH(r0, 1)                        @ r0<- CCBB
5218    mov     r9, rINST, lsr #8           @ r9<- AA
5219    and     r2, r0, #255                @ r2<- BB
5220    mov     r3, r0, lsr #8              @ r3<- CC
5221    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5222    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5223    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5224    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5225    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5226    .if 0
5227    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5228    beq     common_errDivideByZero
5229    .endif
5230    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5231
5232                               @ optional op; may set condition codes
5233    bl      fmod                              @ result<- op, r0-r3 changed
5234    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5235    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5236    GOTO_OPCODE(ip)                     @ jump to next instruction
5237    /* 14-17 instructions */
5238
5239
5240/* ------------------------------ */
5241    .balign 64
5242.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5243/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5244/* File: armv6t2/binop2addr.S */
5245    /*
5246     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5247     * that specifies an instruction that performs "result = r0 op r1".
5248     * This could be an ARM instruction or a function call.  (If the result
5249     * comes back in a register other than r0, you can override "result".)
5250     *
5251     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5252     * vCC (r1).  Useful for integer division and modulus.
5253     *
5254     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5255     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5256     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5257     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5258     */
5259    /* binop/2addr vA, vB */
5260    mov     r3, rINST, lsr #12          @ r3<- B
5261    ubfx    r9, rINST, #8, #4           @ r9<- A
5262    GET_VREG(r1, r3)                    @ r1<- vB
5263    GET_VREG(r0, r9)                    @ r0<- vA
5264    .if 0
5265    cmp     r1, #0                      @ is second operand zero?
5266    beq     common_errDivideByZero
5267    .endif
5268    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5269
5270                               @ optional op; may set condition codes
5271    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5272    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5273    SET_VREG(r0, r9)               @ vAA<- r0
5274    GOTO_OPCODE(ip)                     @ jump to next instruction
5275    /* 10-13 instructions */
5276
5277
5278/* ------------------------------ */
5279    .balign 64
5280.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5281/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5282/* File: armv6t2/binop2addr.S */
5283    /*
5284     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5285     * that specifies an instruction that performs "result = r0 op r1".
5286     * This could be an ARM instruction or a function call.  (If the result
5287     * comes back in a register other than r0, you can override "result".)
5288     *
5289     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5290     * vCC (r1).  Useful for integer division and modulus.
5291     *
5292     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5293     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5294     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5295     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5296     */
5297    /* binop/2addr vA, vB */
5298    mov     r3, rINST, lsr #12          @ r3<- B
5299    ubfx    r9, rINST, #8, #4           @ r9<- A
5300    GET_VREG(r1, r3)                    @ r1<- vB
5301    GET_VREG(r0, r9)                    @ r0<- vA
5302    .if 0
5303    cmp     r1, #0                      @ is second operand zero?
5304    beq     common_errDivideByZero
5305    .endif
5306    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5307
5308                               @ optional op; may set condition codes
5309    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5310    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5311    SET_VREG(r0, r9)               @ vAA<- r0
5312    GOTO_OPCODE(ip)                     @ jump to next instruction
5313    /* 10-13 instructions */
5314
5315
5316/* ------------------------------ */
5317    .balign 64
5318.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5319/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5320/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5321/* File: armv6t2/binop2addr.S */
5322    /*
5323     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5324     * that specifies an instruction that performs "result = r0 op r1".
5325     * This could be an ARM instruction or a function call.  (If the result
5326     * comes back in a register other than r0, you can override "result".)
5327     *
5328     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5329     * vCC (r1).  Useful for integer division and modulus.
5330     *
5331     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5332     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5333     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5334     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5335     */
5336    /* binop/2addr vA, vB */
5337    mov     r3, rINST, lsr #12          @ r3<- B
5338    ubfx    r9, rINST, #8, #4           @ r9<- A
5339    GET_VREG(r1, r3)                    @ r1<- vB
5340    GET_VREG(r0, r9)                    @ r0<- vA
5341    .if 0
5342    cmp     r1, #0                      @ is second operand zero?
5343    beq     common_errDivideByZero
5344    .endif
5345    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5346
5347                               @ optional op; may set condition codes
5348    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5350    SET_VREG(r0, r9)               @ vAA<- r0
5351    GOTO_OPCODE(ip)                     @ jump to next instruction
5352    /* 10-13 instructions */
5353
5354
5355/* ------------------------------ */
5356    .balign 64
5357.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5358/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5359/* File: armv6t2/binop2addr.S */
5360    /*
5361     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5362     * that specifies an instruction that performs "result = r0 op r1".
5363     * This could be an ARM instruction or a function call.  (If the result
5364     * comes back in a register other than r0, you can override "result".)
5365     *
5366     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5367     * vCC (r1).  Useful for integer division and modulus.
5368     *
5369     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5370     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5371     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5372     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5373     */
5374    /* binop/2addr vA, vB */
5375    mov     r3, rINST, lsr #12          @ r3<- B
5376    ubfx    r9, rINST, #8, #4           @ r9<- A
5377    GET_VREG(r1, r3)                    @ r1<- vB
5378    GET_VREG(r0, r9)                    @ r0<- vA
5379    .if 1
5380    cmp     r1, #0                      @ is second operand zero?
5381    beq     common_errDivideByZero
5382    .endif
5383    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5384
5385                               @ optional op; may set condition codes
5386    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5388    SET_VREG(r0, r9)               @ vAA<- r0
5389    GOTO_OPCODE(ip)                     @ jump to next instruction
5390    /* 10-13 instructions */
5391
5392
5393/* ------------------------------ */
5394    .balign 64
5395.L_OP_REM_INT_2ADDR: /* 0xb4 */
5396/* File: armv6t2/OP_REM_INT_2ADDR.S */
5397/* idivmod returns quotient in r0 and remainder in r1 */
5398/* File: armv6t2/binop2addr.S */
5399    /*
5400     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5401     * that specifies an instruction that performs "result = r0 op r1".
5402     * This could be an ARM instruction or a function call.  (If the result
5403     * comes back in a register other than r0, you can override "result".)
5404     *
5405     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5406     * vCC (r1).  Useful for integer division and modulus.
5407     *
5408     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5409     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5410     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5411     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5412     */
5413    /* binop/2addr vA, vB */
5414    mov     r3, rINST, lsr #12          @ r3<- B
5415    ubfx    r9, rINST, #8, #4           @ r9<- A
5416    GET_VREG(r1, r3)                    @ r1<- vB
5417    GET_VREG(r0, r9)                    @ r0<- vA
5418    .if 1
5419    cmp     r1, #0                      @ is second operand zero?
5420    beq     common_errDivideByZero
5421    .endif
5422    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5423
5424                               @ optional op; may set condition codes
5425    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5426    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5427    SET_VREG(r1, r9)               @ vAA<- r1
5428    GOTO_OPCODE(ip)                     @ jump to next instruction
5429    /* 10-13 instructions */
5430
5431
5432/* ------------------------------ */
5433    .balign 64
5434.L_OP_AND_INT_2ADDR: /* 0xb5 */
5435/* File: armv6t2/OP_AND_INT_2ADDR.S */
5436/* File: armv6t2/binop2addr.S */
5437    /*
5438     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5439     * that specifies an instruction that performs "result = r0 op r1".
5440     * This could be an ARM instruction or a function call.  (If the result
5441     * comes back in a register other than r0, you can override "result".)
5442     *
5443     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5444     * vCC (r1).  Useful for integer division and modulus.
5445     *
5446     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5447     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5448     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5449     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5450     */
5451    /* binop/2addr vA, vB */
5452    mov     r3, rINST, lsr #12          @ r3<- B
5453    ubfx    r9, rINST, #8, #4           @ r9<- A
5454    GET_VREG(r1, r3)                    @ r1<- vB
5455    GET_VREG(r0, r9)                    @ r0<- vA
5456    .if 0
5457    cmp     r1, #0                      @ is second operand zero?
5458    beq     common_errDivideByZero
5459    .endif
5460    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5461
5462                               @ optional op; may set condition codes
5463    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5464    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5465    SET_VREG(r0, r9)               @ vAA<- r0
5466    GOTO_OPCODE(ip)                     @ jump to next instruction
5467    /* 10-13 instructions */
5468
5469
5470/* ------------------------------ */
5471    .balign 64
5472.L_OP_OR_INT_2ADDR: /* 0xb6 */
5473/* File: armv6t2/OP_OR_INT_2ADDR.S */
5474/* File: armv6t2/binop2addr.S */
5475    /*
5476     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5477     * that specifies an instruction that performs "result = r0 op r1".
5478     * This could be an ARM instruction or a function call.  (If the result
5479     * comes back in a register other than r0, you can override "result".)
5480     *
5481     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5482     * vCC (r1).  Useful for integer division and modulus.
5483     *
5484     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5485     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5486     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5487     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5488     */
5489    /* binop/2addr vA, vB */
5490    mov     r3, rINST, lsr #12          @ r3<- B
5491    ubfx    r9, rINST, #8, #4           @ r9<- A
5492    GET_VREG(r1, r3)                    @ r1<- vB
5493    GET_VREG(r0, r9)                    @ r0<- vA
5494    .if 0
5495    cmp     r1, #0                      @ is second operand zero?
5496    beq     common_errDivideByZero
5497    .endif
5498    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5499
5500                               @ optional op; may set condition codes
5501    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5502    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5503    SET_VREG(r0, r9)               @ vAA<- r0
5504    GOTO_OPCODE(ip)                     @ jump to next instruction
5505    /* 10-13 instructions */
5506
5507
5508/* ------------------------------ */
5509    .balign 64
5510.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5511/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5512/* File: armv6t2/binop2addr.S */
5513    /*
5514     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5515     * that specifies an instruction that performs "result = r0 op r1".
5516     * This could be an ARM instruction or a function call.  (If the result
5517     * comes back in a register other than r0, you can override "result".)
5518     *
5519     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5520     * vCC (r1).  Useful for integer division and modulus.
5521     *
5522     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5523     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5524     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5525     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5526     */
5527    /* binop/2addr vA, vB */
5528    mov     r3, rINST, lsr #12          @ r3<- B
5529    ubfx    r9, rINST, #8, #4           @ r9<- A
5530    GET_VREG(r1, r3)                    @ r1<- vB
5531    GET_VREG(r0, r9)                    @ r0<- vA
5532    .if 0
5533    cmp     r1, #0                      @ is second operand zero?
5534    beq     common_errDivideByZero
5535    .endif
5536    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5537
5538                               @ optional op; may set condition codes
5539    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5541    SET_VREG(r0, r9)               @ vAA<- r0
5542    GOTO_OPCODE(ip)                     @ jump to next instruction
5543    /* 10-13 instructions */
5544
5545
5546/* ------------------------------ */
5547    .balign 64
5548.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5549/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5550/* File: armv6t2/binop2addr.S */
5551    /*
5552     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5553     * that specifies an instruction that performs "result = r0 op r1".
5554     * This could be an ARM instruction or a function call.  (If the result
5555     * comes back in a register other than r0, you can override "result".)
5556     *
5557     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5558     * vCC (r1).  Useful for integer division and modulus.
5559     *
5560     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5561     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5562     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5563     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5564     */
5565    /* binop/2addr vA, vB */
5566    mov     r3, rINST, lsr #12          @ r3<- B
5567    ubfx    r9, rINST, #8, #4           @ r9<- A
5568    GET_VREG(r1, r3)                    @ r1<- vB
5569    GET_VREG(r0, r9)                    @ r0<- vA
5570    .if 0
5571    cmp     r1, #0                      @ is second operand zero?
5572    beq     common_errDivideByZero
5573    .endif
5574    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5575
5576    and     r1, r1, #31                           @ optional op; may set condition codes
5577    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5578    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5579    SET_VREG(r0, r9)               @ vAA<- r0
5580    GOTO_OPCODE(ip)                     @ jump to next instruction
5581    /* 10-13 instructions */
5582
5583
5584/* ------------------------------ */
5585    .balign 64
5586.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5587/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5588/* File: armv6t2/binop2addr.S */
5589    /*
5590     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5591     * that specifies an instruction that performs "result = r0 op r1".
5592     * This could be an ARM instruction or a function call.  (If the result
5593     * comes back in a register other than r0, you can override "result".)
5594     *
5595     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5596     * vCC (r1).  Useful for integer division and modulus.
5597     *
5598     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5599     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5600     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5601     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5602     */
5603    /* binop/2addr vA, vB */
5604    mov     r3, rINST, lsr #12          @ r3<- B
5605    ubfx    r9, rINST, #8, #4           @ r9<- A
5606    GET_VREG(r1, r3)                    @ r1<- vB
5607    GET_VREG(r0, r9)                    @ r0<- vA
5608    .if 0
5609    cmp     r1, #0                      @ is second operand zero?
5610    beq     common_errDivideByZero
5611    .endif
5612    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5613
5614    and     r1, r1, #31                           @ optional op; may set condition codes
5615    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5617    SET_VREG(r0, r9)               @ vAA<- r0
5618    GOTO_OPCODE(ip)                     @ jump to next instruction
5619    /* 10-13 instructions */
5620
5621
5622/* ------------------------------ */
5623    .balign 64
5624.L_OP_USHR_INT_2ADDR: /* 0xba */
5625/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5626/* File: armv6t2/binop2addr.S */
5627    /*
5628     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5629     * that specifies an instruction that performs "result = r0 op r1".
5630     * This could be an ARM instruction or a function call.  (If the result
5631     * comes back in a register other than r0, you can override "result".)
5632     *
5633     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5634     * vCC (r1).  Useful for integer division and modulus.
5635     *
5636     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5637     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5638     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5639     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5640     */
5641    /* binop/2addr vA, vB */
5642    mov     r3, rINST, lsr #12          @ r3<- B
5643    ubfx    r9, rINST, #8, #4           @ r9<- A
5644    GET_VREG(r1, r3)                    @ r1<- vB
5645    GET_VREG(r0, r9)                    @ r0<- vA
5646    .if 0
5647    cmp     r1, #0                      @ is second operand zero?
5648    beq     common_errDivideByZero
5649    .endif
5650    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5651
5652    and     r1, r1, #31                           @ optional op; may set condition codes
5653    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5655    SET_VREG(r0, r9)               @ vAA<- r0
5656    GOTO_OPCODE(ip)                     @ jump to next instruction
5657    /* 10-13 instructions */
5658
5659
5660/* ------------------------------ */
5661    .balign 64
5662.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5663/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5664/* File: armv6t2/binopWide2addr.S */
5665    /*
5666     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5667     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5668     * This could be an ARM instruction or a function call.  (If the result
5669     * comes back in a register other than r0, you can override "result".)
5670     *
5671     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5672     * vCC (r1).  Useful for integer division and modulus.
5673     *
5674     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5675     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5676     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5677     *      rem-double/2addr
5678     */
5679    /* binop/2addr vA, vB */
5680    mov     r1, rINST, lsr #12          @ r1<- B
5681    ubfx    r9, rINST, #8, #4           @ r9<- A
5682    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5683    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5684    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5685    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5686    .if 0
5687    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5688    beq     common_errDivideByZero
5689    .endif
5690    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5691
5692    adds    r0, r0, r2                           @ optional op; may set condition codes
5693    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5695    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5696    GOTO_OPCODE(ip)                     @ jump to next instruction
5697    /* 12-15 instructions */
5698
5699
5700/* ------------------------------ */
5701    .balign 64
5702.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5703/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5704/* File: armv6t2/binopWide2addr.S */
5705    /*
5706     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5707     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5708     * This could be an ARM instruction or a function call.  (If the result
5709     * comes back in a register other than r0, you can override "result".)
5710     *
5711     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5712     * vCC (r1).  Useful for integer division and modulus.
5713     *
5714     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5715     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5716     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5717     *      rem-double/2addr
5718     */
5719    /* binop/2addr vA, vB */
5720    mov     r1, rINST, lsr #12          @ r1<- B
5721    ubfx    r9, rINST, #8, #4           @ r9<- A
5722    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5723    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5724    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5725    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5726    .if 0
5727    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5728    beq     common_errDivideByZero
5729    .endif
5730    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5731
5732    subs    r0, r0, r2                           @ optional op; may set condition codes
5733    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5734    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5735    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5736    GOTO_OPCODE(ip)                     @ jump to next instruction
5737    /* 12-15 instructions */
5738
5739
5740/* ------------------------------ */
5741    .balign 64
5742.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5743/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5744    /*
5745     * Signed 64-bit integer multiply, "/2addr" version.
5746     *
5747     * See OP_MUL_LONG for an explanation.
5748     *
5749     * We get a little tight on registers, so to avoid looking up &fp[A]
5750     * again we stuff it into rINST.
5751     */
5752    /* mul-long/2addr vA, vB */
5753    mov     r1, rINST, lsr #12          @ r1<- B
5754    ubfx    r9, rINST, #8, #4           @ r9<- A
5755    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5756    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5757    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5758    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5759    mul     ip, r2, r1                  @  ip<- ZxW
5760    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5761    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5762    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5763    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5764    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5765    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5766    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5767    GOTO_OPCODE(ip)                     @ jump to next instruction
5768
5769/* ------------------------------ */
5770    .balign 64
5771.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5772/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5773/* File: armv6t2/binopWide2addr.S */
5774    /*
5775     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5776     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5777     * This could be an ARM instruction or a function call.  (If the result
5778     * comes back in a register other than r0, you can override "result".)
5779     *
5780     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5781     * vCC (r1).  Useful for integer division and modulus.
5782     *
5783     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5784     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5785     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5786     *      rem-double/2addr
5787     */
5788    /* binop/2addr vA, vB */
5789    mov     r1, rINST, lsr #12          @ r1<- B
5790    ubfx    r9, rINST, #8, #4           @ r9<- A
5791    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5792    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5793    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5794    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5795    .if 1
5796    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5797    beq     common_errDivideByZero
5798    .endif
5799    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5800
5801                               @ optional op; may set condition codes
5802    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5804    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5805    GOTO_OPCODE(ip)                     @ jump to next instruction
5806    /* 12-15 instructions */
5807
5808
5809/* ------------------------------ */
5810    .balign 64
5811.L_OP_REM_LONG_2ADDR: /* 0xbf */
5812/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5813/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5814/* File: armv6t2/binopWide2addr.S */
5815    /*
5816     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5817     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5818     * This could be an ARM instruction or a function call.  (If the result
5819     * comes back in a register other than r0, you can override "result".)
5820     *
5821     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5822     * vCC (r1).  Useful for integer division and modulus.
5823     *
5824     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5825     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5826     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5827     *      rem-double/2addr
5828     */
5829    /* binop/2addr vA, vB */
5830    mov     r1, rINST, lsr #12          @ r1<- B
5831    ubfx    r9, rINST, #8, #4           @ r9<- A
5832    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5833    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5834    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5835    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5836    .if 1
5837    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5838    beq     common_errDivideByZero
5839    .endif
5840    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5841
5842                               @ optional op; may set condition codes
5843    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5845    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5846    GOTO_OPCODE(ip)                     @ jump to next instruction
5847    /* 12-15 instructions */
5848
5849
5850/* ------------------------------ */
5851    .balign 64
5852.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5853/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5854/* File: armv6t2/binopWide2addr.S */
5855    /*
5856     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5857     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5858     * This could be an ARM instruction or a function call.  (If the result
5859     * comes back in a register other than r0, you can override "result".)
5860     *
5861     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5862     * vCC (r1).  Useful for integer division and modulus.
5863     *
5864     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5865     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5866     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5867     *      rem-double/2addr
5868     */
5869    /* binop/2addr vA, vB */
5870    mov     r1, rINST, lsr #12          @ r1<- B
5871    ubfx    r9, rINST, #8, #4           @ r9<- A
5872    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5873    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5874    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5875    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5876    .if 0
5877    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5878    beq     common_errDivideByZero
5879    .endif
5880    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5881
5882    and     r0, r0, r2                           @ optional op; may set condition codes
5883    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5885    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5886    GOTO_OPCODE(ip)                     @ jump to next instruction
5887    /* 12-15 instructions */
5888
5889
5890/* ------------------------------ */
5891    .balign 64
5892.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5893/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5894/* File: armv6t2/binopWide2addr.S */
5895    /*
5896     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5897     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5898     * This could be an ARM instruction or a function call.  (If the result
5899     * comes back in a register other than r0, you can override "result".)
5900     *
5901     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5902     * vCC (r1).  Useful for integer division and modulus.
5903     *
5904     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5905     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5906     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5907     *      rem-double/2addr
5908     */
5909    /* binop/2addr vA, vB */
5910    mov     r1, rINST, lsr #12          @ r1<- B
5911    ubfx    r9, rINST, #8, #4           @ r9<- A
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 0
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    orr     r0, r0, r2                           @ optional op; may set condition codes
5923    orr     r1, r1, r3                              @ 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    .balign 64
5932.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5933/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5934/* File: armv6t2/binopWide2addr.S */
5935    /*
5936     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5937     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5938     * This could be an ARM instruction or a function call.  (If the result
5939     * comes back in a register other than r0, you can override "result".)
5940     *
5941     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5942     * vCC (r1).  Useful for integer division and modulus.
5943     *
5944     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5945     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5946     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5947     *      rem-double/2addr
5948     */
5949    /* binop/2addr vA, vB */
5950    mov     r1, rINST, lsr #12          @ r1<- B
5951    ubfx    r9, rINST, #8, #4           @ r9<- A
5952    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5953    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5954    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5955    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5956    .if 0
5957    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5958    beq     common_errDivideByZero
5959    .endif
5960    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5961
5962    eor     r0, r0, r2                           @ optional op; may set condition codes
5963    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5964    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5965    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5966    GOTO_OPCODE(ip)                     @ jump to next instruction
5967    /* 12-15 instructions */
5968
5969
5970/* ------------------------------ */
5971    .balign 64
5972.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5973/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
5974    /*
5975     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5976     * 32-bit shift distance.
5977     */
5978    /* shl-long/2addr vA, vB */
5979    mov     r3, rINST, lsr #12          @ r3<- B
5980    ubfx    r9, rINST, #8, #4           @ r9<- A
5981    GET_VREG(r2, r3)                    @ r2<- vB
5982    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5983    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5984    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5985
5986    mov     r1, r1, asl r2              @  r1<- r1 << r2
5987    rsb     r3, r2, #32                 @  r3<- 32 - r2
5988    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5989    subs    ip, r2, #32                 @  ip<- r2 - 32
5990    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5991    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5992    mov     r0, r0, asl r2              @  r0<- r0 << r2
5993    b       .LOP_SHL_LONG_2ADDR_finish
5994
5995/* ------------------------------ */
5996    .balign 64
5997.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
5998/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
5999    /*
6000     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6001     * 32-bit shift distance.
6002     */
6003    /* shr-long/2addr vA, vB */
6004    mov     r3, rINST, lsr #12          @ r3<- B
6005    ubfx    r9, rINST, #8, #4           @ r9<- A
6006    GET_VREG(r2, r3)                    @ r2<- vB
6007    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6008    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6009    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6010
6011    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6012    rsb     r3, r2, #32                 @  r3<- 32 - r2
6013    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6014    subs    ip, r2, #32                 @  ip<- r2 - 32
6015    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6016    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6017    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6018    b       .LOP_SHR_LONG_2ADDR_finish
6019
6020/* ------------------------------ */
6021    .balign 64
6022.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6023/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6024    /*
6025     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6026     * 32-bit shift distance.
6027     */
6028    /* ushr-long/2addr vA, vB */
6029    mov     r3, rINST, lsr #12          @ r3<- B
6030    ubfx    r9, rINST, #8, #4           @ r9<- A
6031    GET_VREG(r2, r3)                    @ r2<- vB
6032    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6033    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6034    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6035
6036    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6037    rsb     r3, r2, #32                 @  r3<- 32 - r2
6038    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6039    subs    ip, r2, #32                 @  ip<- r2 - 32
6040    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6041    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6042    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6043    b       .LOP_USHR_LONG_2ADDR_finish
6044
6045/* ------------------------------ */
6046    .balign 64
6047.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6048/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6049/* File: arm-vfp/fbinop2addr.S */
6050    /*
6051     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6052     * an "instr" line that specifies an instruction that performs
6053     * "s2 = s0 op s1".
6054     *
6055     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6056     */
6057    /* binop/2addr vA, vB */
6058    mov     r3, rINST, lsr #12          @ r3<- B
6059    mov     r9, rINST, lsr #8           @ r9<- A+
6060    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6061    and     r9, r9, #15                 @ r9<- A
6062    flds    s1, [r3]                    @ s1<- vB
6063    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6064    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6065    flds    s0, [r9]                    @ s0<- vA
6066
6067    fadds   s2, s0, s1                              @ s2<- op
6068    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6069    fsts    s2, [r9]                    @ vAA<- s2
6070    GOTO_OPCODE(ip)                     @ jump to next instruction
6071
6072
6073/* ------------------------------ */
6074    .balign 64
6075.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6076/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6077/* File: arm-vfp/fbinop2addr.S */
6078    /*
6079     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6080     * an "instr" line that specifies an instruction that performs
6081     * "s2 = s0 op s1".
6082     *
6083     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6084     */
6085    /* binop/2addr vA, vB */
6086    mov     r3, rINST, lsr #12          @ r3<- B
6087    mov     r9, rINST, lsr #8           @ r9<- A+
6088    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6089    and     r9, r9, #15                 @ r9<- A
6090    flds    s1, [r3]                    @ s1<- vB
6091    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6092    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6093    flds    s0, [r9]                    @ s0<- vA
6094
6095    fsubs   s2, s0, s1                              @ s2<- op
6096    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6097    fsts    s2, [r9]                    @ vAA<- s2
6098    GOTO_OPCODE(ip)                     @ jump to next instruction
6099
6100
6101/* ------------------------------ */
6102    .balign 64
6103.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6104/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6105/* File: arm-vfp/fbinop2addr.S */
6106    /*
6107     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6108     * an "instr" line that specifies an instruction that performs
6109     * "s2 = s0 op s1".
6110     *
6111     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6112     */
6113    /* binop/2addr vA, vB */
6114    mov     r3, rINST, lsr #12          @ r3<- B
6115    mov     r9, rINST, lsr #8           @ r9<- A+
6116    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6117    and     r9, r9, #15                 @ r9<- A
6118    flds    s1, [r3]                    @ s1<- vB
6119    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6120    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6121    flds    s0, [r9]                    @ s0<- vA
6122
6123    fmuls   s2, s0, s1                              @ s2<- op
6124    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6125    fsts    s2, [r9]                    @ vAA<- s2
6126    GOTO_OPCODE(ip)                     @ jump to next instruction
6127
6128
6129/* ------------------------------ */
6130    .balign 64
6131.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6132/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6133/* File: arm-vfp/fbinop2addr.S */
6134    /*
6135     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6136     * an "instr" line that specifies an instruction that performs
6137     * "s2 = s0 op s1".
6138     *
6139     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6140     */
6141    /* binop/2addr vA, vB */
6142    mov     r3, rINST, lsr #12          @ r3<- B
6143    mov     r9, rINST, lsr #8           @ r9<- A+
6144    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6145    and     r9, r9, #15                 @ r9<- A
6146    flds    s1, [r3]                    @ s1<- vB
6147    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6148    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6149    flds    s0, [r9]                    @ s0<- vA
6150
6151    fdivs   s2, s0, s1                              @ s2<- op
6152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6153    fsts    s2, [r9]                    @ vAA<- s2
6154    GOTO_OPCODE(ip)                     @ jump to next instruction
6155
6156
6157/* ------------------------------ */
6158    .balign 64
6159.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6160/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6161/* EABI doesn't define a float remainder function, but libm does */
6162/* File: armv6t2/binop2addr.S */
6163    /*
6164     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6165     * that specifies an instruction that performs "result = r0 op r1".
6166     * This could be an ARM instruction or a function call.  (If the result
6167     * comes back in a register other than r0, you can override "result".)
6168     *
6169     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6170     * vCC (r1).  Useful for integer division and modulus.
6171     *
6172     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6173     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6174     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6175     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6176     */
6177    /* binop/2addr vA, vB */
6178    mov     r3, rINST, lsr #12          @ r3<- B
6179    ubfx    r9, rINST, #8, #4           @ r9<- A
6180    GET_VREG(r1, r3)                    @ r1<- vB
6181    GET_VREG(r0, r9)                    @ r0<- vA
6182    .if 0
6183    cmp     r1, #0                      @ is second operand zero?
6184    beq     common_errDivideByZero
6185    .endif
6186    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6187
6188                               @ optional op; may set condition codes
6189    bl      fmodf                              @ r0<- op, r0-r3 changed
6190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6191    SET_VREG(r0, r9)               @ vAA<- r0
6192    GOTO_OPCODE(ip)                     @ jump to next instruction
6193    /* 10-13 instructions */
6194
6195
6196/* ------------------------------ */
6197    .balign 64
6198.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6199/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6200/* File: arm-vfp/fbinopWide2addr.S */
6201    /*
6202     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6203     * an "instr" line that specifies an instruction that performs
6204     * "d2 = d0 op d1".
6205     *
6206     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6207     *      div-double/2addr
6208     */
6209    /* binop/2addr vA, vB */
6210    mov     r3, rINST, lsr #12          @ r3<- B
6211    mov     r9, rINST, lsr #8           @ r9<- A+
6212    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6213    and     r9, r9, #15                 @ r9<- A
6214    fldd    d1, [r3]                    @ d1<- vB
6215    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6216    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6217    fldd    d0, [r9]                    @ d0<- vA
6218
6219    faddd   d2, d0, d1                              @ d2<- op
6220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6221    fstd    d2, [r9]                    @ vAA<- d2
6222    GOTO_OPCODE(ip)                     @ jump to next instruction
6223
6224
6225/* ------------------------------ */
6226    .balign 64
6227.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6228/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6229/* File: arm-vfp/fbinopWide2addr.S */
6230    /*
6231     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6232     * an "instr" line that specifies an instruction that performs
6233     * "d2 = d0 op d1".
6234     *
6235     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6236     *      div-double/2addr
6237     */
6238    /* binop/2addr vA, vB */
6239    mov     r3, rINST, lsr #12          @ r3<- B
6240    mov     r9, rINST, lsr #8           @ r9<- A+
6241    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6242    and     r9, r9, #15                 @ r9<- A
6243    fldd    d1, [r3]                    @ d1<- vB
6244    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6245    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6246    fldd    d0, [r9]                    @ d0<- vA
6247
6248    fsubd   d2, d0, d1                              @ d2<- op
6249    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6250    fstd    d2, [r9]                    @ vAA<- d2
6251    GOTO_OPCODE(ip)                     @ jump to next instruction
6252
6253
6254/* ------------------------------ */
6255    .balign 64
6256.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6257/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6258/* File: arm-vfp/fbinopWide2addr.S */
6259    /*
6260     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6261     * an "instr" line that specifies an instruction that performs
6262     * "d2 = d0 op d1".
6263     *
6264     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6265     *      div-double/2addr
6266     */
6267    /* binop/2addr vA, vB */
6268    mov     r3, rINST, lsr #12          @ r3<- B
6269    mov     r9, rINST, lsr #8           @ r9<- A+
6270    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6271    and     r9, r9, #15                 @ r9<- A
6272    fldd    d1, [r3]                    @ d1<- vB
6273    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6274    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6275    fldd    d0, [r9]                    @ d0<- vA
6276
6277    fmuld   d2, d0, d1                              @ d2<- op
6278    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6279    fstd    d2, [r9]                    @ vAA<- d2
6280    GOTO_OPCODE(ip)                     @ jump to next instruction
6281
6282
6283/* ------------------------------ */
6284    .balign 64
6285.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6286/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6287/* File: arm-vfp/fbinopWide2addr.S */
6288    /*
6289     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6290     * an "instr" line that specifies an instruction that performs
6291     * "d2 = d0 op d1".
6292     *
6293     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6294     *      div-double/2addr
6295     */
6296    /* binop/2addr vA, vB */
6297    mov     r3, rINST, lsr #12          @ r3<- B
6298    mov     r9, rINST, lsr #8           @ r9<- A+
6299    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6300    and     r9, r9, #15                 @ r9<- A
6301    fldd    d1, [r3]                    @ d1<- vB
6302    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6303    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6304    fldd    d0, [r9]                    @ d0<- vA
6305
6306    fdivd   d2, d0, d1                              @ d2<- op
6307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6308    fstd    d2, [r9]                    @ vAA<- d2
6309    GOTO_OPCODE(ip)                     @ jump to next instruction
6310
6311
6312/* ------------------------------ */
6313    .balign 64
6314.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6315/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6316/* EABI doesn't define a double remainder function, but libm does */
6317/* File: armv6t2/binopWide2addr.S */
6318    /*
6319     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6320     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6321     * This could be an ARM instruction or a function call.  (If the result
6322     * comes back in a register other than r0, you can override "result".)
6323     *
6324     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6325     * vCC (r1).  Useful for integer division and modulus.
6326     *
6327     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6328     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6329     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6330     *      rem-double/2addr
6331     */
6332    /* binop/2addr vA, vB */
6333    mov     r1, rINST, lsr #12          @ r1<- B
6334    ubfx    r9, rINST, #8, #4           @ r9<- A
6335    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6336    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6337    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6338    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6339    .if 0
6340    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6341    beq     common_errDivideByZero
6342    .endif
6343    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6344
6345                               @ optional op; may set condition codes
6346    bl      fmod                              @ result<- op, r0-r3 changed
6347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6348    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6349    GOTO_OPCODE(ip)                     @ jump to next instruction
6350    /* 12-15 instructions */
6351
6352
6353/* ------------------------------ */
6354    .balign 64
6355.L_OP_ADD_INT_LIT16: /* 0xd0 */
6356/* File: armv6t2/OP_ADD_INT_LIT16.S */
6357/* File: armv6t2/binopLit16.S */
6358    /*
6359     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6360     * that specifies an instruction that performs "result = r0 op r1".
6361     * This could be an ARM instruction or a function call.  (If the result
6362     * comes back in a register other than r0, you can override "result".)
6363     *
6364     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6365     * vCC (r1).  Useful for integer division and modulus.
6366     *
6367     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6368     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6369     */
6370    /* binop/lit16 vA, vB, #+CCCC */
6371    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6372    mov     r2, rINST, lsr #12          @ r2<- B
6373    ubfx    r9, rINST, #8, #4           @ r9<- A
6374    GET_VREG(r0, r2)                    @ r0<- vB
6375    .if 0
6376    cmp     r1, #0                      @ is second operand zero?
6377    beq     common_errDivideByZero
6378    .endif
6379    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6380
6381    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6382    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6383    SET_VREG(r0, r9)               @ vAA<- r0
6384    GOTO_OPCODE(ip)                     @ jump to next instruction
6385    /* 10-13 instructions */
6386
6387
6388/* ------------------------------ */
6389    .balign 64
6390.L_OP_RSUB_INT: /* 0xd1 */
6391/* File: armv6t2/OP_RSUB_INT.S */
6392/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6393/* File: armv6t2/binopLit16.S */
6394    /*
6395     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6396     * that specifies an instruction that performs "result = r0 op r1".
6397     * This could be an ARM instruction or a function call.  (If the result
6398     * comes back in a register other than r0, you can override "result".)
6399     *
6400     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6401     * vCC (r1).  Useful for integer division and modulus.
6402     *
6403     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6404     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6405     */
6406    /* binop/lit16 vA, vB, #+CCCC */
6407    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6408    mov     r2, rINST, lsr #12          @ r2<- B
6409    ubfx    r9, rINST, #8, #4           @ r9<- A
6410    GET_VREG(r0, r2)                    @ r0<- vB
6411    .if 0
6412    cmp     r1, #0                      @ is second operand zero?
6413    beq     common_errDivideByZero
6414    .endif
6415    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6416
6417    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6418    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6419    SET_VREG(r0, r9)               @ vAA<- r0
6420    GOTO_OPCODE(ip)                     @ jump to next instruction
6421    /* 10-13 instructions */
6422
6423
6424/* ------------------------------ */
6425    .balign 64
6426.L_OP_MUL_INT_LIT16: /* 0xd2 */
6427/* File: armv6t2/OP_MUL_INT_LIT16.S */
6428/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6429/* File: armv6t2/binopLit16.S */
6430    /*
6431     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6432     * that specifies an instruction that performs "result = r0 op r1".
6433     * This could be an ARM instruction or a function call.  (If the result
6434     * comes back in a register other than r0, you can override "result".)
6435     *
6436     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6437     * vCC (r1).  Useful for integer division and modulus.
6438     *
6439     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6440     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6441     */
6442    /* binop/lit16 vA, vB, #+CCCC */
6443    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6444    mov     r2, rINST, lsr #12          @ r2<- B
6445    ubfx    r9, rINST, #8, #4           @ r9<- A
6446    GET_VREG(r0, r2)                    @ r0<- vB
6447    .if 0
6448    cmp     r1, #0                      @ is second operand zero?
6449    beq     common_errDivideByZero
6450    .endif
6451    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6452
6453    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6455    SET_VREG(r0, r9)               @ vAA<- r0
6456    GOTO_OPCODE(ip)                     @ jump to next instruction
6457    /* 10-13 instructions */
6458
6459
6460/* ------------------------------ */
6461    .balign 64
6462.L_OP_DIV_INT_LIT16: /* 0xd3 */
6463/* File: armv6t2/OP_DIV_INT_LIT16.S */
6464/* File: armv6t2/binopLit16.S */
6465    /*
6466     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6467     * that specifies an instruction that performs "result = r0 op r1".
6468     * This could be an ARM instruction or a function call.  (If the result
6469     * comes back in a register other than r0, you can override "result".)
6470     *
6471     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6472     * vCC (r1).  Useful for integer division and modulus.
6473     *
6474     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6475     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6476     */
6477    /* binop/lit16 vA, vB, #+CCCC */
6478    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6479    mov     r2, rINST, lsr #12          @ r2<- B
6480    ubfx    r9, rINST, #8, #4           @ r9<- A
6481    GET_VREG(r0, r2)                    @ r0<- vB
6482    .if 1
6483    cmp     r1, #0                      @ is second operand zero?
6484    beq     common_errDivideByZero
6485    .endif
6486    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6487
6488    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6489    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6490    SET_VREG(r0, r9)               @ vAA<- r0
6491    GOTO_OPCODE(ip)                     @ jump to next instruction
6492    /* 10-13 instructions */
6493
6494
6495/* ------------------------------ */
6496    .balign 64
6497.L_OP_REM_INT_LIT16: /* 0xd4 */
6498/* File: armv6t2/OP_REM_INT_LIT16.S */
6499/* idivmod returns quotient in r0 and remainder in r1 */
6500/* File: armv6t2/binopLit16.S */
6501    /*
6502     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6503     * that specifies an instruction that performs "result = r0 op r1".
6504     * This could be an ARM instruction or a function call.  (If the result
6505     * comes back in a register other than r0, you can override "result".)
6506     *
6507     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6508     * vCC (r1).  Useful for integer division and modulus.
6509     *
6510     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6511     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6512     */
6513    /* binop/lit16 vA, vB, #+CCCC */
6514    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6515    mov     r2, rINST, lsr #12          @ r2<- B
6516    ubfx    r9, rINST, #8, #4           @ r9<- A
6517    GET_VREG(r0, r2)                    @ r0<- vB
6518    .if 1
6519    cmp     r1, #0                      @ is second operand zero?
6520    beq     common_errDivideByZero
6521    .endif
6522    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6523
6524    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6525    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6526    SET_VREG(r1, r9)               @ vAA<- r1
6527    GOTO_OPCODE(ip)                     @ jump to next instruction
6528    /* 10-13 instructions */
6529
6530
6531/* ------------------------------ */
6532    .balign 64
6533.L_OP_AND_INT_LIT16: /* 0xd5 */
6534/* File: armv6t2/OP_AND_INT_LIT16.S */
6535/* File: armv6t2/binopLit16.S */
6536    /*
6537     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6538     * that specifies an instruction that performs "result = r0 op r1".
6539     * This could be an ARM instruction or a function call.  (If the result
6540     * comes back in a register other than r0, you can override "result".)
6541     *
6542     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6543     * vCC (r1).  Useful for integer division and modulus.
6544     *
6545     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6546     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6547     */
6548    /* binop/lit16 vA, vB, #+CCCC */
6549    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6550    mov     r2, rINST, lsr #12          @ r2<- B
6551    ubfx    r9, rINST, #8, #4           @ r9<- A
6552    GET_VREG(r0, r2)                    @ r0<- vB
6553    .if 0
6554    cmp     r1, #0                      @ is second operand zero?
6555    beq     common_errDivideByZero
6556    .endif
6557    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6558
6559    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6560    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6561    SET_VREG(r0, r9)               @ vAA<- r0
6562    GOTO_OPCODE(ip)                     @ jump to next instruction
6563    /* 10-13 instructions */
6564
6565
6566/* ------------------------------ */
6567    .balign 64
6568.L_OP_OR_INT_LIT16: /* 0xd6 */
6569/* File: armv6t2/OP_OR_INT_LIT16.S */
6570/* File: armv6t2/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    ubfx    r9, rINST, #8, #4           @ r9<- A
6587    GET_VREG(r0, r2)                    @ r0<- vB
6588    .if 0
6589    cmp     r1, #0                      @ is second operand zero?
6590    beq     common_errDivideByZero
6591    .endif
6592    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6593
6594    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6596    SET_VREG(r0, r9)               @ vAA<- r0
6597    GOTO_OPCODE(ip)                     @ jump to next instruction
6598    /* 10-13 instructions */
6599
6600
6601/* ------------------------------ */
6602    .balign 64
6603.L_OP_XOR_INT_LIT16: /* 0xd7 */
6604/* File: armv6t2/OP_XOR_INT_LIT16.S */
6605/* File: armv6t2/binopLit16.S */
6606    /*
6607     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6608     * that specifies an instruction that performs "result = r0 op r1".
6609     * This could be an ARM instruction or a function call.  (If the result
6610     * comes back in a register other than r0, you can override "result".)
6611     *
6612     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6613     * vCC (r1).  Useful for integer division and modulus.
6614     *
6615     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6616     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6617     */
6618    /* binop/lit16 vA, vB, #+CCCC */
6619    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6620    mov     r2, rINST, lsr #12          @ r2<- B
6621    ubfx    r9, rINST, #8, #4           @ r9<- A
6622    GET_VREG(r0, r2)                    @ r0<- vB
6623    .if 0
6624    cmp     r1, #0                      @ is second operand zero?
6625    beq     common_errDivideByZero
6626    .endif
6627    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6628
6629    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6630    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6631    SET_VREG(r0, r9)               @ vAA<- r0
6632    GOTO_OPCODE(ip)                     @ jump to next instruction
6633    /* 10-13 instructions */
6634
6635
6636/* ------------------------------ */
6637    .balign 64
6638.L_OP_ADD_INT_LIT8: /* 0xd8 */
6639/* File: armv5te/OP_ADD_INT_LIT8.S */
6640/* File: armv5te/binopLit8.S */
6641    /*
6642     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6643     * that specifies an instruction that performs "result = r0 op r1".
6644     * This could be an ARM instruction or a function call.  (If the result
6645     * comes back in a register other than r0, you can override "result".)
6646     *
6647     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6648     * vCC (r1).  Useful for integer division and modulus.
6649     *
6650     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6651     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6652     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6653     */
6654    /* binop/lit8 vAA, vBB, #+CC */
6655    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6656    mov     r9, rINST, lsr #8           @ r9<- AA
6657    and     r2, r3, #255                @ r2<- BB
6658    GET_VREG(r0, r2)                    @ r0<- vBB
6659    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6660    .if 0
6661    @cmp     r1, #0                      @ is second operand zero?
6662    beq     common_errDivideByZero
6663    .endif
6664    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6665
6666                               @ optional op; may set condition codes
6667    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6668    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6669    SET_VREG(r0, r9)               @ vAA<- r0
6670    GOTO_OPCODE(ip)                     @ jump to next instruction
6671    /* 10-12 instructions */
6672
6673
6674/* ------------------------------ */
6675    .balign 64
6676.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6677/* File: armv5te/OP_RSUB_INT_LIT8.S */
6678/* File: armv5te/binopLit8.S */
6679    /*
6680     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6681     * that specifies an instruction that performs "result = r0 op r1".
6682     * This could be an ARM instruction or a function call.  (If the result
6683     * comes back in a register other than r0, you can override "result".)
6684     *
6685     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6686     * vCC (r1).  Useful for integer division and modulus.
6687     *
6688     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6689     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6690     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6691     */
6692    /* binop/lit8 vAA, vBB, #+CC */
6693    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6694    mov     r9, rINST, lsr #8           @ r9<- AA
6695    and     r2, r3, #255                @ r2<- BB
6696    GET_VREG(r0, r2)                    @ r0<- vBB
6697    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6698    .if 0
6699    @cmp     r1, #0                      @ is second operand zero?
6700    beq     common_errDivideByZero
6701    .endif
6702    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6703
6704                               @ optional op; may set condition codes
6705    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6706    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6707    SET_VREG(r0, r9)               @ vAA<- r0
6708    GOTO_OPCODE(ip)                     @ jump to next instruction
6709    /* 10-12 instructions */
6710
6711
6712/* ------------------------------ */
6713    .balign 64
6714.L_OP_MUL_INT_LIT8: /* 0xda */
6715/* File: armv5te/OP_MUL_INT_LIT8.S */
6716/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6717/* File: armv5te/binopLit8.S */
6718    /*
6719     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6720     * that specifies an instruction that performs "result = r0 op r1".
6721     * This could be an ARM instruction or a function call.  (If the result
6722     * comes back in a register other than r0, you can override "result".)
6723     *
6724     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6725     * vCC (r1).  Useful for integer division and modulus.
6726     *
6727     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6728     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6729     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6730     */
6731    /* binop/lit8 vAA, vBB, #+CC */
6732    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6733    mov     r9, rINST, lsr #8           @ r9<- AA
6734    and     r2, r3, #255                @ r2<- BB
6735    GET_VREG(r0, r2)                    @ r0<- vBB
6736    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6737    .if 0
6738    @cmp     r1, #0                      @ is second operand zero?
6739    beq     common_errDivideByZero
6740    .endif
6741    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6742
6743                               @ optional op; may set condition codes
6744    mul     r0, r1, r0                              @ 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-12 instructions */
6749
6750
6751/* ------------------------------ */
6752    .balign 64
6753.L_OP_DIV_INT_LIT8: /* 0xdb */
6754/* File: armv5te/OP_DIV_INT_LIT8.S */
6755/* File: armv5te/binopLit8.S */
6756    /*
6757     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6758     * that specifies an instruction that performs "result = r0 op r1".
6759     * This could be an ARM instruction or a function call.  (If the result
6760     * comes back in a register other than r0, you can override "result".)
6761     *
6762     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6763     * vCC (r1).  Useful for integer division and modulus.
6764     *
6765     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6766     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6767     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6768     */
6769    /* binop/lit8 vAA, vBB, #+CC */
6770    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6771    mov     r9, rINST, lsr #8           @ r9<- AA
6772    and     r2, r3, #255                @ r2<- BB
6773    GET_VREG(r0, r2)                    @ r0<- vBB
6774    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6775    .if 1
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                               @ optional op; may set condition codes
6782    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6783    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6784    SET_VREG(r0, r9)               @ vAA<- r0
6785    GOTO_OPCODE(ip)                     @ jump to next instruction
6786    /* 10-12 instructions */
6787
6788
6789/* ------------------------------ */
6790    .balign 64
6791.L_OP_REM_INT_LIT8: /* 0xdc */
6792/* File: armv5te/OP_REM_INT_LIT8.S */
6793/* idivmod returns quotient in r0 and remainder in r1 */
6794/* File: armv5te/binopLit8.S */
6795    /*
6796     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6797     * that specifies an instruction that performs "result = r0 op r1".
6798     * This could be an ARM instruction or a function call.  (If the result
6799     * comes back in a register other than r0, you can override "result".)
6800     *
6801     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6802     * vCC (r1).  Useful for integer division and modulus.
6803     *
6804     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6805     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6806     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6807     */
6808    /* binop/lit8 vAA, vBB, #+CC */
6809    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6810    mov     r9, rINST, lsr #8           @ r9<- AA
6811    and     r2, r3, #255                @ r2<- BB
6812    GET_VREG(r0, r2)                    @ r0<- vBB
6813    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6814    .if 1
6815    @cmp     r1, #0                      @ is second operand zero?
6816    beq     common_errDivideByZero
6817    .endif
6818    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6819
6820                               @ optional op; may set condition codes
6821    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6823    SET_VREG(r1, r9)               @ vAA<- r1
6824    GOTO_OPCODE(ip)                     @ jump to next instruction
6825    /* 10-12 instructions */
6826
6827
6828/* ------------------------------ */
6829    .balign 64
6830.L_OP_AND_INT_LIT8: /* 0xdd */
6831/* File: armv5te/OP_AND_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    and     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    .balign 64
6868.L_OP_OR_INT_LIT8: /* 0xde */
6869/* File: armv5te/OP_OR_INT_LIT8.S */
6870/* File: armv5te/binopLit8.S */
6871    /*
6872     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6873     * that specifies an instruction that performs "result = r0 op r1".
6874     * This could be an ARM instruction or a function call.  (If the result
6875     * comes back in a register other than r0, you can override "result".)
6876     *
6877     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6878     * vCC (r1).  Useful for integer division and modulus.
6879     *
6880     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6881     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6882     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6883     */
6884    /* binop/lit8 vAA, vBB, #+CC */
6885    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6886    mov     r9, rINST, lsr #8           @ r9<- AA
6887    and     r2, r3, #255                @ r2<- BB
6888    GET_VREG(r0, r2)                    @ r0<- vBB
6889    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6890    .if 0
6891    @cmp     r1, #0                      @ is second operand zero?
6892    beq     common_errDivideByZero
6893    .endif
6894    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6895
6896                               @ optional op; may set condition codes
6897    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6899    SET_VREG(r0, r9)               @ vAA<- r0
6900    GOTO_OPCODE(ip)                     @ jump to next instruction
6901    /* 10-12 instructions */
6902
6903
6904/* ------------------------------ */
6905    .balign 64
6906.L_OP_XOR_INT_LIT8: /* 0xdf */
6907/* File: armv5te/OP_XOR_INT_LIT8.S */
6908/* File: armv5te/binopLit8.S */
6909    /*
6910     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6911     * that specifies an instruction that performs "result = r0 op r1".
6912     * This could be an ARM instruction or a function call.  (If the result
6913     * comes back in a register other than r0, you can override "result".)
6914     *
6915     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6916     * vCC (r1).  Useful for integer division and modulus.
6917     *
6918     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6919     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6920     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6921     */
6922    /* binop/lit8 vAA, vBB, #+CC */
6923    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6924    mov     r9, rINST, lsr #8           @ r9<- AA
6925    and     r2, r3, #255                @ r2<- BB
6926    GET_VREG(r0, r2)                    @ r0<- vBB
6927    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6928    .if 0
6929    @cmp     r1, #0                      @ is second operand zero?
6930    beq     common_errDivideByZero
6931    .endif
6932    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6933
6934                               @ optional op; may set condition codes
6935    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6936    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6937    SET_VREG(r0, r9)               @ vAA<- r0
6938    GOTO_OPCODE(ip)                     @ jump to next instruction
6939    /* 10-12 instructions */
6940
6941
6942/* ------------------------------ */
6943    .balign 64
6944.L_OP_SHL_INT_LIT8: /* 0xe0 */
6945/* File: armv5te/OP_SHL_INT_LIT8.S */
6946/* File: armv5te/binopLit8.S */
6947    /*
6948     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6949     * that specifies an instruction that performs "result = r0 op r1".
6950     * This could be an ARM instruction or a function call.  (If the result
6951     * comes back in a register other than r0, you can override "result".)
6952     *
6953     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6954     * vCC (r1).  Useful for integer division and modulus.
6955     *
6956     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6957     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6958     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6959     */
6960    /* binop/lit8 vAA, vBB, #+CC */
6961    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6962    mov     r9, rINST, lsr #8           @ r9<- AA
6963    and     r2, r3, #255                @ r2<- BB
6964    GET_VREG(r0, r2)                    @ r0<- vBB
6965    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6966    .if 0
6967    @cmp     r1, #0                      @ is second operand zero?
6968    beq     common_errDivideByZero
6969    .endif
6970    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6971
6972    and     r1, r1, #31                           @ optional op; may set condition codes
6973    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
6974    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6975    SET_VREG(r0, r9)               @ vAA<- r0
6976    GOTO_OPCODE(ip)                     @ jump to next instruction
6977    /* 10-12 instructions */
6978
6979
6980/* ------------------------------ */
6981    .balign 64
6982.L_OP_SHR_INT_LIT8: /* 0xe1 */
6983/* File: armv5te/OP_SHR_INT_LIT8.S */
6984/* File: armv5te/binopLit8.S */
6985    /*
6986     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6987     * that specifies an instruction that performs "result = r0 op r1".
6988     * This could be an ARM instruction or a function call.  (If the result
6989     * comes back in a register other than r0, you can override "result".)
6990     *
6991     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6992     * vCC (r1).  Useful for integer division and modulus.
6993     *
6994     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6995     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6996     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6997     */
6998    /* binop/lit8 vAA, vBB, #+CC */
6999    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7000    mov     r9, rINST, lsr #8           @ r9<- AA
7001    and     r2, r3, #255                @ r2<- BB
7002    GET_VREG(r0, r2)                    @ r0<- vBB
7003    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7004    .if 0
7005    @cmp     r1, #0                      @ is second operand zero?
7006    beq     common_errDivideByZero
7007    .endif
7008    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7009
7010    and     r1, r1, #31                           @ optional op; may set condition codes
7011    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7012    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7013    SET_VREG(r0, r9)               @ vAA<- r0
7014    GOTO_OPCODE(ip)                     @ jump to next instruction
7015    /* 10-12 instructions */
7016
7017
7018/* ------------------------------ */
7019    .balign 64
7020.L_OP_USHR_INT_LIT8: /* 0xe2 */
7021/* File: armv5te/OP_USHR_INT_LIT8.S */
7022/* File: armv5te/binopLit8.S */
7023    /*
7024     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7025     * that specifies an instruction that performs "result = r0 op r1".
7026     * This could be an ARM instruction or a function call.  (If the result
7027     * comes back in a register other than r0, you can override "result".)
7028     *
7029     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7030     * vCC (r1).  Useful for integer division and modulus.
7031     *
7032     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7033     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7034     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7035     */
7036    /* binop/lit8 vAA, vBB, #+CC */
7037    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7038    mov     r9, rINST, lsr #8           @ r9<- AA
7039    and     r2, r3, #255                @ r2<- BB
7040    GET_VREG(r0, r2)                    @ r0<- vBB
7041    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7042    .if 0
7043    @cmp     r1, #0                      @ is second operand zero?
7044    beq     common_errDivideByZero
7045    .endif
7046    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7047
7048    and     r1, r1, #31                           @ optional op; may set condition codes
7049    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7051    SET_VREG(r0, r9)               @ vAA<- r0
7052    GOTO_OPCODE(ip)                     @ jump to next instruction
7053    /* 10-12 instructions */
7054
7055
7056/* ------------------------------ */
7057    .balign 64
7058.L_OP_IGET_VOLATILE: /* 0xe3 */
7059/* File: armv5te/OP_IGET_VOLATILE.S */
7060/* File: armv5te/OP_IGET.S */
7061    /*
7062     * General 32-bit instance field get.
7063     *
7064     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7065     */
7066    /* op vA, vB, field@CCCC */
7067    mov     r0, rINST, lsr #12          @ r0<- B
7068    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7069    FETCH(r1, 1)                        @ r1<- field ref CCCC
7070    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7071    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7072    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7073    cmp     r0, #0                      @ is resolved entry null?
7074    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
70758:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7076    EXPORT_PC()                         @ resolve() could throw
7077    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7078    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7079    cmp     r0, #0
7080    bne     .LOP_IGET_VOLATILE_finish
7081    b       common_exceptionThrown
7082
7083
7084/* ------------------------------ */
7085    .balign 64
7086.L_OP_IPUT_VOLATILE: /* 0xe4 */
7087/* File: armv5te/OP_IPUT_VOLATILE.S */
7088/* File: armv5te/OP_IPUT.S */
7089    /*
7090     * General 32-bit instance field put.
7091     *
7092     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
7093     */
7094    /* op vA, vB, field@CCCC */
7095    mov     r0, rINST, lsr #12          @ r0<- B
7096    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7097    FETCH(r1, 1)                        @ r1<- field ref CCCC
7098    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7099    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7100    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7101    cmp     r0, #0                      @ is resolved entry null?
7102    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71038:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7104    EXPORT_PC()                         @ resolve() could throw
7105    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7106    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7107    cmp     r0, #0                      @ success?
7108    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7109    b       common_exceptionThrown
7110
7111
7112/* ------------------------------ */
7113    .balign 64
7114.L_OP_SGET_VOLATILE: /* 0xe5 */
7115/* File: armv5te/OP_SGET_VOLATILE.S */
7116/* File: armv5te/OP_SGET.S */
7117    /*
7118     * General 32-bit SGET handler.
7119     *
7120     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7121     */
7122    /* op vAA, field@BBBB */
7123    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7124    FETCH(r1, 1)                        @ r1<- field ref BBBB
7125    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7126    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7127    cmp     r0, #0                      @ is resolved entry null?
7128    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7129.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7130    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7131    SMP_DMB                            @ acquiring load
7132    mov     r2, rINST, lsr #8           @ r2<- AA
7133    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7134    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7136    GOTO_OPCODE(ip)                     @ jump to next instruction
7137
7138
7139/* ------------------------------ */
7140    .balign 64
7141.L_OP_SPUT_VOLATILE: /* 0xe6 */
7142/* File: armv5te/OP_SPUT_VOLATILE.S */
7143/* File: armv5te/OP_SPUT.S */
7144    /*
7145     * General 32-bit SPUT handler.
7146     *
7147     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
7148     */
7149    /* op vAA, field@BBBB */
7150    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7151    FETCH(r1, 1)                        @ r1<- field ref BBBB
7152    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7153    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7154    cmp     r0, #0                      @ is resolved entry null?
7155    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7156.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7157    mov     r2, rINST, lsr #8           @ r2<- AA
7158    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7159    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7160    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7161    SMP_DMB                            @ releasing store
7162    str     r1, [r0, #offStaticField_value] @ field<- vAA
7163    GOTO_OPCODE(ip)                     @ jump to next instruction
7164
7165
7166/* ------------------------------ */
7167    .balign 64
7168.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7169/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7170/* File: armv5te/OP_IGET.S */
7171    /*
7172     * General 32-bit instance field get.
7173     *
7174     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7175     */
7176    /* op vA, vB, field@CCCC */
7177    mov     r0, rINST, lsr #12          @ r0<- B
7178    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7179    FETCH(r1, 1)                        @ r1<- field ref CCCC
7180    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7181    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7182    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7183    cmp     r0, #0                      @ is resolved entry null?
7184    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
71858:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7186    EXPORT_PC()                         @ resolve() could throw
7187    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7188    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7189    cmp     r0, #0
7190    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7191    b       common_exceptionThrown
7192
7193
7194/* ------------------------------ */
7195    .balign 64
7196.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7197/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7198/* File: armv5te/OP_IGET_WIDE.S */
7199    /*
7200     * Wide 32-bit instance field get.
7201     */
7202    /* iget-wide vA, vB, field@CCCC */
7203    mov     r0, rINST, lsr #12          @ r0<- B
7204    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7205    FETCH(r1, 1)                        @ r1<- field ref CCCC
7206    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7207    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7208    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7209    cmp     r0, #0                      @ is resolved entry null?
7210    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72118:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7212    EXPORT_PC()                         @ resolve() could throw
7213    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7214    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7215    cmp     r0, #0
7216    bne     .LOP_IGET_WIDE_VOLATILE_finish
7217    b       common_exceptionThrown
7218
7219
7220/* ------------------------------ */
7221    .balign 64
7222.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7223/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7224/* File: armv5te/OP_IPUT_WIDE.S */
7225    /* iput-wide vA, vB, field@CCCC */
7226    mov     r0, rINST, lsr #12          @ r0<- B
7227    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7228    FETCH(r1, 1)                        @ r1<- field ref CCCC
7229    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7230    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7231    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7232    cmp     r0, #0                      @ is resolved entry null?
7233    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72348:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7235    EXPORT_PC()                         @ resolve() could throw
7236    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7237    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7238    cmp     r0, #0                      @ success?
7239    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7240    b       common_exceptionThrown
7241
7242
7243/* ------------------------------ */
7244    .balign 64
7245.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7246/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7247/* File: armv5te/OP_SGET_WIDE.S */
7248    /*
7249     * 64-bit SGET handler.
7250     */
7251    /* sget-wide vAA, field@BBBB */
7252    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7253    FETCH(r1, 1)                        @ r1<- field ref BBBB
7254    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7255    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7256    cmp     r0, #0                      @ is resolved entry null?
7257    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7258.LOP_SGET_WIDE_VOLATILE_finish:
7259    mov     r9, rINST, lsr #8           @ r9<- AA
7260    .if 1
7261    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7262    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7263    .else
7264    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7265    .endif
7266    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7267    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7268    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7270    GOTO_OPCODE(ip)                     @ jump to next instruction
7271
7272
7273/* ------------------------------ */
7274    .balign 64
7275.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7276/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7277/* File: armv5te/OP_SPUT_WIDE.S */
7278    /*
7279     * 64-bit SPUT handler.
7280     */
7281    /* sput-wide vAA, field@BBBB */
7282    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7283    FETCH(r1, 1)                        @ r1<- field ref BBBB
7284    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7285    mov     r9, rINST, lsr #8           @ r9<- AA
7286    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7287    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7288    cmp     r2, #0                      @ is resolved entry null?
7289    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7290.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7291    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7292    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7293    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7294    .if 1
7295    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7296    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7297    .else
7298    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7299    .endif
7300    GOTO_OPCODE(r10)                    @ jump to next instruction
7301
7302
7303/* ------------------------------ */
7304    .balign 64
7305.L_OP_BREAKPOINT: /* 0xec */
7306/* File: armv5te/OP_BREAKPOINT.S */
7307/* File: armv5te/unused.S */
7308    bl      common_abort
7309
7310
7311/* ------------------------------ */
7312    .balign 64
7313.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7314/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7315    /*
7316     * Handle a throw-verification-error instruction.  This throws an
7317     * exception for an error discovered during verification.  The
7318     * exception is indicated by AA, with some detail provided by BBBB.
7319     */
7320    /* op AA, ref@BBBB */
7321    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7322    FETCH(r2, 1)                        @ r2<- BBBB
7323    EXPORT_PC()                         @ export the PC
7324    mov     r1, rINST, lsr #8           @ r1<- AA
7325    bl      dvmThrowVerificationError   @ always throws
7326    b       common_exceptionThrown      @ handle exception
7327
7328/* ------------------------------ */
7329    .balign 64
7330.L_OP_EXECUTE_INLINE: /* 0xee */
7331/* File: armv5te/OP_EXECUTE_INLINE.S */
7332    /*
7333     * Execute a "native inline" instruction.
7334     *
7335     * We need to call an InlineOp4Func:
7336     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7337     *
7338     * The first four args are in r0-r3, pointer to return value storage
7339     * is on the stack.  The function's return value is a flag that tells
7340     * us if an exception was thrown.
7341     */
7342    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7343    FETCH(r10, 1)                       @ r10<- BBBB
7344    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7345    EXPORT_PC()                         @ can throw
7346    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7347    mov     r0, rINST, lsr #12          @ r0<- B
7348    str     r1, [sp]                    @ push &glue->retval
7349    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7350    add     sp, sp, #8                  @ pop stack
7351    cmp     r0, #0                      @ test boolean result of inline
7352    beq     common_exceptionThrown      @ returned false, handle exception
7353    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7354    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7355    GOTO_OPCODE(ip)                     @ jump to next instruction
7356
7357/* ------------------------------ */
7358    .balign 64
7359.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7360/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7361    /*
7362     * Execute a "native inline" instruction, using "/range" semantics.
7363     * Same idea as execute-inline, but we get the args differently.
7364     *
7365     * We need to call an InlineOp4Func:
7366     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7367     *
7368     * The first four args are in r0-r3, pointer to return value storage
7369     * is on the stack.  The function's return value is a flag that tells
7370     * us if an exception was thrown.
7371     */
7372    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7373    FETCH(r10, 1)                       @ r10<- BBBB
7374    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7375    EXPORT_PC()                         @ can throw
7376    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7377    mov     r0, rINST, lsr #8           @ r0<- AA
7378    str     r1, [sp]                    @ push &glue->retval
7379    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7380    add     sp, sp, #8                  @ pop stack
7381    cmp     r0, #0                      @ test boolean result of inline
7382    beq     common_exceptionThrown      @ returned false, handle exception
7383    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7384    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7385    GOTO_OPCODE(ip)                     @ jump to next instruction
7386
7387/* ------------------------------ */
7388    .balign 64
7389.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7390/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7391    /*
7392     * invoke-direct-empty is a no-op in a "standard" interpreter.
7393     */
7394    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7395    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7396    GOTO_OPCODE(ip)                     @ execute it
7397
7398/* ------------------------------ */
7399    .balign 64
7400.L_OP_UNUSED_F1: /* 0xf1 */
7401/* File: armv5te/OP_UNUSED_F1.S */
7402/* File: armv5te/unused.S */
7403    bl      common_abort
7404
7405
7406/* ------------------------------ */
7407    .balign 64
7408.L_OP_IGET_QUICK: /* 0xf2 */
7409/* File: armv6t2/OP_IGET_QUICK.S */
7410    /* For: iget-quick, iget-object-quick */
7411    /* op vA, vB, offset@CCCC */
7412    mov     r2, rINST, lsr #12          @ r2<- B
7413    FETCH(r1, 1)                        @ r1<- field byte offset
7414    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7415    ubfx    r2, rINST, #8, #4           @ r2<- A
7416    cmp     r3, #0                      @ check object for null
7417    beq     common_errNullObject        @ object was null
7418    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7419    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7420    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7421    SET_VREG(r0, r2)                    @ fp[A]<- r0
7422    GOTO_OPCODE(ip)                     @ jump to next instruction
7423
7424/* ------------------------------ */
7425    .balign 64
7426.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7427/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7428    /* iget-wide-quick vA, vB, offset@CCCC */
7429    mov     r2, rINST, lsr #12          @ r2<- B
7430    FETCH(ip, 1)                        @ ip<- field byte offset
7431    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7432    ubfx    r2, rINST, #8, #4           @ r2<- A
7433    cmp     r3, #0                      @ check object for null
7434    beq     common_errNullObject        @ object was null
7435    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7437    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7438    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7439    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7440    GOTO_OPCODE(ip)                     @ jump to next instruction
7441
7442/* ------------------------------ */
7443    .balign 64
7444.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7445/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7446/* File: armv5te/OP_IGET_QUICK.S */
7447    /* For: iget-quick, iget-object-quick */
7448    /* op vA, vB, offset@CCCC */
7449    mov     r2, rINST, lsr #12          @ r2<- B
7450    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7451    FETCH(r1, 1)                        @ r1<- field byte offset
7452    cmp     r3, #0                      @ check object for null
7453    mov     r2, rINST, lsr #8           @ r2<- A(+)
7454    beq     common_errNullObject        @ object was null
7455    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7456    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7457    and     r2, r2, #15
7458    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7459    SET_VREG(r0, r2)                    @ fp[A]<- r0
7460    GOTO_OPCODE(ip)                     @ jump to next instruction
7461
7462
7463/* ------------------------------ */
7464    .balign 64
7465.L_OP_IPUT_QUICK: /* 0xf5 */
7466/* File: armv6t2/OP_IPUT_QUICK.S */
7467    /* For: iput-quick, iput-object-quick */
7468    /* op vA, vB, offset@CCCC */
7469    mov     r2, rINST, lsr #12          @ r2<- B
7470    FETCH(r1, 1)                        @ r1<- field byte offset
7471    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7472    ubfx    r2, rINST, #8, #4           @ r2<- A
7473    cmp     r3, #0                      @ check object for null
7474    beq     common_errNullObject        @ object was null
7475    GET_VREG(r0, r2)                    @ r0<- fp[A]
7476    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7477    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7478    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7479    GOTO_OPCODE(ip)                     @ jump to next instruction
7480
7481/* ------------------------------ */
7482    .balign 64
7483.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7484/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7485    /* iput-wide-quick vA, vB, offset@CCCC */
7486    mov     r1, rINST, lsr #12          @ r1<- B
7487    ubfx    r0, rINST, #8, #4           @ r0<- A
7488    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7489    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7490    cmp     r2, #0                      @ check object for null
7491    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7492    beq     common_errNullObject        @ object was null
7493    FETCH(r3, 1)                        @ r3<- field byte offset
7494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7495    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7496    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7497    GOTO_OPCODE(ip)                     @ jump to next instruction
7498
7499/* ------------------------------ */
7500    .balign 64
7501.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7502/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7503/* File: armv5te/OP_IPUT_QUICK.S */
7504    /* For: iput-quick, iput-object-quick */
7505    /* op vA, vB, offset@CCCC */
7506    mov     r2, rINST, lsr #12          @ r2<- B
7507    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7508    FETCH(r1, 1)                        @ r1<- field byte offset
7509    cmp     r3, #0                      @ check object for null
7510    mov     r2, rINST, lsr #8           @ r2<- A(+)
7511    beq     common_errNullObject        @ object was null
7512    and     r2, r2, #15
7513    GET_VREG(r0, r2)                    @ r0<- fp[A]
7514    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7515    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7517    GOTO_OPCODE(ip)                     @ jump to next instruction
7518
7519
7520/* ------------------------------ */
7521    .balign 64
7522.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7523/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7524    /*
7525     * Handle an optimized virtual method call.
7526     *
7527     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7528     */
7529    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7530    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7531    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7532    FETCH(r1, 1)                        @ r1<- BBBB
7533    .if     (!0)
7534    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7535    .endif
7536    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7537    cmp     r2, #0                      @ is "this" null?
7538    beq     common_errNullObject        @ null "this", throw exception
7539    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7540    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7541    EXPORT_PC()                         @ invoke must export
7542    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7543    bl      common_invokeMethodNoRange @ continue on
7544
7545/* ------------------------------ */
7546    .balign 64
7547.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7548/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7549/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7550    /*
7551     * Handle an optimized virtual method call.
7552     *
7553     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7554     */
7555    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7556    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7557    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7558    FETCH(r1, 1)                        @ r1<- BBBB
7559    .if     (!1)
7560    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7561    .endif
7562    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7563    cmp     r2, #0                      @ is "this" null?
7564    beq     common_errNullObject        @ null "this", throw exception
7565    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7566    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7567    EXPORT_PC()                         @ invoke must export
7568    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7569    bl      common_invokeMethodRange @ continue on
7570
7571
7572/* ------------------------------ */
7573    .balign 64
7574.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7575/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7576    /*
7577     * Handle an optimized "super" method call.
7578     *
7579     * for: [opt] invoke-super-quick, invoke-super-quick/range
7580     */
7581    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7582    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7583    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7584    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7585    .if     (!0)
7586    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7587    .endif
7588    FETCH(r1, 1)                        @ r1<- BBBB
7589    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7590    EXPORT_PC()                         @ must export for invoke
7591    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7592    GET_VREG(r3, r10)                   @ r3<- "this"
7593    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7594    cmp     r3, #0                      @ null "this" ref?
7595    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7596    beq     common_errNullObject        @ "this" is null, throw exception
7597    bl      common_invokeMethodNoRange @ continue on
7598
7599/* ------------------------------ */
7600    .balign 64
7601.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7602/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7603/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7604    /*
7605     * Handle an optimized "super" method call.
7606     *
7607     * for: [opt] invoke-super-quick, invoke-super-quick/range
7608     */
7609    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7610    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7611    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7612    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7613    .if     (!1)
7614    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7615    .endif
7616    FETCH(r1, 1)                        @ r1<- BBBB
7617    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7618    EXPORT_PC()                         @ must export for invoke
7619    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7620    GET_VREG(r3, r10)                   @ r3<- "this"
7621    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7622    cmp     r3, #0                      @ null "this" ref?
7623    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7624    beq     common_errNullObject        @ "this" is null, throw exception
7625    bl      common_invokeMethodRange @ continue on
7626
7627
7628/* ------------------------------ */
7629    .balign 64
7630.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7631/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7632/* File: armv5te/OP_IPUT.S */
7633    /*
7634     * General 32-bit instance field put.
7635     *
7636     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
7637     */
7638    /* op vA, vB, field@CCCC */
7639    mov     r0, rINST, lsr #12          @ r0<- B
7640    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7641    FETCH(r1, 1)                        @ r1<- field ref CCCC
7642    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7643    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7644    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7645    cmp     r0, #0                      @ is resolved entry null?
7646    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76478:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7648    EXPORT_PC()                         @ resolve() could throw
7649    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7650    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7651    cmp     r0, #0                      @ success?
7652    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7653    b       common_exceptionThrown
7654
7655
7656/* ------------------------------ */
7657    .balign 64
7658.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7659/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7660/* File: armv5te/OP_SGET.S */
7661    /*
7662     * General 32-bit SGET handler.
7663     *
7664     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7665     */
7666    /* op vAA, field@BBBB */
7667    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7668    FETCH(r1, 1)                        @ r1<- field ref BBBB
7669    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7670    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7671    cmp     r0, #0                      @ is resolved entry null?
7672    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7673.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7674    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7675    SMP_DMB                            @ acquiring load
7676    mov     r2, rINST, lsr #8           @ r2<- AA
7677    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7678    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7680    GOTO_OPCODE(ip)                     @ jump to next instruction
7681
7682
7683/* ------------------------------ */
7684    .balign 64
7685.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7686/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7687/* File: armv5te/OP_SPUT.S */
7688    /*
7689     * General 32-bit SPUT handler.
7690     *
7691     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
7692     */
7693    /* op vAA, field@BBBB */
7694    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7695    FETCH(r1, 1)                        @ r1<- field ref BBBB
7696    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7697    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7698    cmp     r0, #0                      @ is resolved entry null?
7699    beq     .LOP_SPUT_OBJECT_VOLATILE_resolve         @ yes, do resolve
7700.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
7701    mov     r2, rINST, lsr #8           @ r2<- AA
7702    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7703    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7704    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7705    SMP_DMB                            @ releasing store
7706    str     r1, [r0, #offStaticField_value] @ field<- vAA
7707    GOTO_OPCODE(ip)                     @ jump to next instruction
7708
7709
7710/* ------------------------------ */
7711    .balign 64
7712.L_OP_UNUSED_FF: /* 0xff */
7713/* File: armv5te/OP_UNUSED_FF.S */
7714/* File: armv5te/unused.S */
7715    bl      common_abort
7716
7717
7718
7719    .balign 64
7720    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7721    .global dvmAsmInstructionEnd
7722dvmAsmInstructionEnd:
7723
7724/*
7725 * ===========================================================================
7726 *  Sister implementations
7727 * ===========================================================================
7728 */
7729    .global dvmAsmSisterStart
7730    .type   dvmAsmSisterStart, %function
7731    .text
7732    .balign 4
7733dvmAsmSisterStart:
7734
7735/* continuation for OP_CONST_STRING */
7736
7737    /*
7738     * Continuation if the String has not yet been resolved.
7739     *  r1: BBBB (String ref)
7740     *  r9: target register
7741     */
7742.LOP_CONST_STRING_resolve:
7743    EXPORT_PC()
7744    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7745    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7746    bl      dvmResolveString            @ r0<- String reference
7747    cmp     r0, #0                      @ failed?
7748    beq     common_exceptionThrown      @ yup, handle the exception
7749    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7751    SET_VREG(r0, r9)                    @ vAA<- r0
7752    GOTO_OPCODE(ip)                     @ jump to next instruction
7753
7754/* continuation for OP_CONST_STRING_JUMBO */
7755
7756    /*
7757     * Continuation if the String has not yet been resolved.
7758     *  r1: BBBBBBBB (String ref)
7759     *  r9: target register
7760     */
7761.LOP_CONST_STRING_JUMBO_resolve:
7762    EXPORT_PC()
7763    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7764    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7765    bl      dvmResolveString            @ r0<- String reference
7766    cmp     r0, #0                      @ failed?
7767    beq     common_exceptionThrown      @ yup, handle the exception
7768    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7770    SET_VREG(r0, r9)                    @ vAA<- r0
7771    GOTO_OPCODE(ip)                     @ jump to next instruction
7772
7773/* continuation for OP_CONST_CLASS */
7774
7775    /*
7776     * Continuation if the Class has not yet been resolved.
7777     *  r1: BBBB (Class ref)
7778     *  r9: target register
7779     */
7780.LOP_CONST_CLASS_resolve:
7781    EXPORT_PC()
7782    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7783    mov     r2, #1                      @ r2<- true
7784    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7785    bl      dvmResolveClass             @ r0<- Class reference
7786    cmp     r0, #0                      @ failed?
7787    beq     common_exceptionThrown      @ yup, handle the exception
7788    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7790    SET_VREG(r0, r9)                    @ vAA<- r0
7791    GOTO_OPCODE(ip)                     @ jump to next instruction
7792
7793/* continuation for OP_CHECK_CAST */
7794
7795    /*
7796     * Trivial test failed, need to perform full check.  This is common.
7797     *  r0 holds obj->clazz
7798     *  r1 holds class resolved from BBBB
7799     *  r9 holds object
7800     */
7801.LOP_CHECK_CAST_fullcheck:
7802    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7803    cmp     r0, #0                      @ failed?
7804    bne     .LOP_CHECK_CAST_okay            @ no, success
7805
7806    @ A cast has failed.  We need to throw a ClassCastException with the
7807    @ class of the object that failed to be cast.
7808    EXPORT_PC()                         @ about to throw
7809    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7810    ldr     r0, .LstrClassCastExceptionPtr
7811    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7812    bl      dvmThrowExceptionWithClassMessage
7813    b       common_exceptionThrown
7814
7815    /*
7816     * Resolution required.  This is the least-likely path.
7817     *
7818     *  r2 holds BBBB
7819     *  r9 holds object
7820     */
7821.LOP_CHECK_CAST_resolve:
7822    EXPORT_PC()                         @ resolve() could throw
7823    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7824    mov     r1, r2                      @ r1<- BBBB
7825    mov     r2, #0                      @ r2<- false
7826    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7827    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7828    cmp     r0, #0                      @ got null?
7829    beq     common_exceptionThrown      @ yes, handle exception
7830    mov     r1, r0                      @ r1<- class resolved from BBB
7831    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7832    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7833
7834.LstrClassCastExceptionPtr:
7835    .word   .LstrClassCastException
7836
7837/* continuation for OP_INSTANCE_OF */
7838
7839    /*
7840     * Trivial test failed, need to perform full check.  This is common.
7841     *  r0 holds obj->clazz
7842     *  r1 holds class resolved from BBBB
7843     *  r9 holds A
7844     */
7845.LOP_INSTANCE_OF_fullcheck:
7846    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7847    @ fall through to OP_INSTANCE_OF_store
7848
7849    /*
7850     * r0 holds boolean result
7851     * r9 holds A
7852     */
7853.LOP_INSTANCE_OF_store:
7854    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7855    SET_VREG(r0, r9)                    @ vA<- r0
7856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7857    GOTO_OPCODE(ip)                     @ jump to next instruction
7858
7859    /*
7860     * Trivial test succeeded, save and bail.
7861     *  r9 holds A
7862     */
7863.LOP_INSTANCE_OF_trivial:
7864    mov     r0, #1                      @ indicate success
7865    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7866    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7867    SET_VREG(r0, r9)                    @ vA<- r0
7868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7869    GOTO_OPCODE(ip)                     @ jump to next instruction
7870
7871    /*
7872     * Resolution required.  This is the least-likely path.
7873     *
7874     *  r3 holds BBBB
7875     *  r9 holds A
7876     */
7877.LOP_INSTANCE_OF_resolve:
7878    EXPORT_PC()                         @ resolve() could throw
7879    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7880    mov     r1, r3                      @ r1<- BBBB
7881    mov     r2, #1                      @ r2<- true
7882    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7883    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7884    cmp     r0, #0                      @ got null?
7885    beq     common_exceptionThrown      @ yes, handle exception
7886    mov     r1, r0                      @ r1<- class resolved from BBB
7887    mov     r3, rINST, lsr #12          @ r3<- B
7888    GET_VREG(r0, r3)                    @ r0<- vB (object)
7889    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7890    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7891
7892/* continuation for OP_NEW_INSTANCE */
7893
7894    .balign 32                          @ minimize cache lines
7895.LOP_NEW_INSTANCE_finish: @ r0=new object
7896    mov     r3, rINST, lsr #8           @ r3<- AA
7897    cmp     r0, #0                      @ failed?
7898    beq     common_exceptionThrown      @ yes, handle the exception
7899    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7901    SET_VREG(r0, r3)                    @ vAA<- r0
7902    GOTO_OPCODE(ip)                     @ jump to next instruction
7903
7904    /*
7905     * Class initialization required.
7906     *
7907     *  r0 holds class object
7908     */
7909.LOP_NEW_INSTANCE_needinit:
7910    mov     r9, r0                      @ save r0
7911    bl      dvmInitClass                @ initialize class
7912    cmp     r0, #0                      @ check boolean result
7913    mov     r0, r9                      @ restore r0
7914    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7915    b       common_exceptionThrown      @ failed, deal with init exception
7916
7917    /*
7918     * Resolution required.  This is the least-likely path.
7919     *
7920     *  r1 holds BBBB
7921     */
7922.LOP_NEW_INSTANCE_resolve:
7923    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7924    mov     r2, #0                      @ r2<- false
7925    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7926    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7927    cmp     r0, #0                      @ got null?
7928    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7929    b       common_exceptionThrown      @ yes, handle exception
7930
7931.LstrInstantiationErrorPtr:
7932    .word   .LstrInstantiationError
7933
7934/* continuation for OP_NEW_ARRAY */
7935
7936
7937    /*
7938     * Resolve class.  (This is an uncommon case.)
7939     *
7940     *  r1 holds array length
7941     *  r2 holds class ref CCCC
7942     */
7943.LOP_NEW_ARRAY_resolve:
7944    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7945    mov     r9, r1                      @ r9<- length (save)
7946    mov     r1, r2                      @ r1<- CCCC
7947    mov     r2, #0                      @ r2<- false
7948    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7949    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7950    cmp     r0, #0                      @ got null?
7951    mov     r1, r9                      @ r1<- length (restore)
7952    beq     common_exceptionThrown      @ yes, handle exception
7953    @ fall through to OP_NEW_ARRAY_finish
7954
7955    /*
7956     * Finish allocation.
7957     *
7958     *  r0 holds class
7959     *  r1 holds array length
7960     */
7961.LOP_NEW_ARRAY_finish:
7962    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7963    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7964    cmp     r0, #0                      @ failed?
7965    mov     r2, rINST, lsr #8           @ r2<- A+
7966    beq     common_exceptionThrown      @ yes, handle the exception
7967    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7968    and     r2, r2, #15                 @ r2<- A
7969    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7970    SET_VREG(r0, r2)                    @ vA<- r0
7971    GOTO_OPCODE(ip)                     @ jump to next instruction
7972
7973/* continuation for OP_FILLED_NEW_ARRAY */
7974
7975    /*
7976     * On entry:
7977     *  r0 holds array class
7978     *  r10 holds AA or BA
7979     */
7980.LOP_FILLED_NEW_ARRAY_continue:
7981    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7982    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7983    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7984    .if     0
7985    mov     r1, r10                     @ r1<- AA (length)
7986    .else
7987    mov     r1, r10, lsr #4             @ r1<- B (length)
7988    .endif
7989    cmp     r3, #'I'                    @ array of ints?
7990    cmpne   r3, #'L'                    @ array of objects?
7991    cmpne   r3, #'['                    @ array of arrays?
7992    mov     r9, r1                      @ save length in r9
7993    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7994    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7995    cmp     r0, #0                      @ null return?
7996    beq     common_exceptionThrown      @ alloc failed, handle exception
7997
7998    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7999    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8000    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8001    subs    r9, r9, #1                  @ length--, check for neg
8002    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8003    bmi     2f                          @ was zero, bail
8004
8005    @ copy values from registers into the array
8006    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8007    .if     0
8008    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80091:  ldr     r3, [r2], #4                @ r3<- *r2++
8010    subs    r9, r9, #1                  @ count--
8011    str     r3, [r0], #4                @ *contents++ = vX
8012    bpl     1b
8013    @ continue at 2
8014    .else
8015    cmp     r9, #4                      @ length was initially 5?
8016    and     r2, r10, #15                @ r2<- A
8017    bne     1f                          @ <= 4 args, branch
8018    GET_VREG(r3, r2)                    @ r3<- vA
8019    sub     r9, r9, #1                  @ count--
8020    str     r3, [r0, #16]               @ contents[4] = vA
80211:  and     r2, r1, #15                 @ r2<- F/E/D/C
8022    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8023    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8024    subs    r9, r9, #1                  @ count--
8025    str     r3, [r0], #4                @ *contents++ = vX
8026    bpl     1b
8027    @ continue at 2
8028    .endif
8029
80302:
8031    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8032    GOTO_OPCODE(ip)                     @ execute it
8033
8034    /*
8035     * Throw an exception indicating that we have not implemented this
8036     * mode of filled-new-array.
8037     */
8038.LOP_FILLED_NEW_ARRAY_notimpl:
8039    ldr     r0, .L_strInternalError
8040    ldr     r1, .L_strFilledNewArrayNotImpl
8041    bl      dvmThrowException
8042    b       common_exceptionThrown
8043
8044    .if     (!0)                 @ define in one or the other, not both
8045.L_strFilledNewArrayNotImpl:
8046    .word   .LstrFilledNewArrayNotImpl
8047.L_strInternalError:
8048    .word   .LstrInternalError
8049    .endif
8050
8051/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8052
8053    /*
8054     * On entry:
8055     *  r0 holds array class
8056     *  r10 holds AA or BA
8057     */
8058.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8059    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8060    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8061    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8062    .if     1
8063    mov     r1, r10                     @ r1<- AA (length)
8064    .else
8065    mov     r1, r10, lsr #4             @ r1<- B (length)
8066    .endif
8067    cmp     r3, #'I'                    @ array of ints?
8068    cmpne   r3, #'L'                    @ array of objects?
8069    cmpne   r3, #'['                    @ array of arrays?
8070    mov     r9, r1                      @ save length in r9
8071    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8072    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8073    cmp     r0, #0                      @ null return?
8074    beq     common_exceptionThrown      @ alloc failed, handle exception
8075
8076    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8077    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8078    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8079    subs    r9, r9, #1                  @ length--, check for neg
8080    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8081    bmi     2f                          @ was zero, bail
8082
8083    @ copy values from registers into the array
8084    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8085    .if     1
8086    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80871:  ldr     r3, [r2], #4                @ r3<- *r2++
8088    subs    r9, r9, #1                  @ count--
8089    str     r3, [r0], #4                @ *contents++ = vX
8090    bpl     1b
8091    @ continue at 2
8092    .else
8093    cmp     r9, #4                      @ length was initially 5?
8094    and     r2, r10, #15                @ r2<- A
8095    bne     1f                          @ <= 4 args, branch
8096    GET_VREG(r3, r2)                    @ r3<- vA
8097    sub     r9, r9, #1                  @ count--
8098    str     r3, [r0, #16]               @ contents[4] = vA
80991:  and     r2, r1, #15                 @ r2<- F/E/D/C
8100    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8101    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8102    subs    r9, r9, #1                  @ count--
8103    str     r3, [r0], #4                @ *contents++ = vX
8104    bpl     1b
8105    @ continue at 2
8106    .endif
8107
81082:
8109    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8110    GOTO_OPCODE(ip)                     @ execute it
8111
8112    /*
8113     * Throw an exception indicating that we have not implemented this
8114     * mode of filled-new-array.
8115     */
8116.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8117    ldr     r0, .L_strInternalError
8118    ldr     r1, .L_strFilledNewArrayNotImpl
8119    bl      dvmThrowException
8120    b       common_exceptionThrown
8121
8122    .if     (!1)                 @ define in one or the other, not both
8123.L_strFilledNewArrayNotImpl:
8124    .word   .LstrFilledNewArrayNotImpl
8125.L_strInternalError:
8126    .word   .LstrInternalError
8127    .endif
8128
8129/* continuation for OP_CMPL_FLOAT */
8130.LOP_CMPL_FLOAT_finish:
8131    SET_VREG(r0, r9)                    @ vAA<- r0
8132    GOTO_OPCODE(ip)                     @ jump to next instruction
8133
8134/* continuation for OP_CMPG_FLOAT */
8135.LOP_CMPG_FLOAT_finish:
8136    SET_VREG(r0, r9)                    @ vAA<- r0
8137    GOTO_OPCODE(ip)                     @ jump to next instruction
8138
8139/* continuation for OP_CMPL_DOUBLE */
8140.LOP_CMPL_DOUBLE_finish:
8141    SET_VREG(r0, r9)                    @ vAA<- r0
8142    GOTO_OPCODE(ip)                     @ jump to next instruction
8143
8144/* continuation for OP_CMPG_DOUBLE */
8145.LOP_CMPG_DOUBLE_finish:
8146    SET_VREG(r0, r9)                    @ vAA<- r0
8147    GOTO_OPCODE(ip)                     @ jump to next instruction
8148
8149/* continuation for OP_CMP_LONG */
8150
8151.LOP_CMP_LONG_less:
8152    mvn     r1, #0                      @ r1<- -1
8153    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8154    @ instead, we just replicate the tail end.
8155    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8156    SET_VREG(r1, r9)                    @ vAA<- r1
8157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8158    GOTO_OPCODE(ip)                     @ jump to next instruction
8159
8160.LOP_CMP_LONG_greater:
8161    mov     r1, #1                      @ r1<- 1
8162    @ fall through to _finish
8163
8164.LOP_CMP_LONG_finish:
8165    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8166    SET_VREG(r1, r9)                    @ vAA<- r1
8167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8168    GOTO_OPCODE(ip)                     @ jump to next instruction
8169
8170/* continuation for OP_AGET_WIDE */
8171
8172.LOP_AGET_WIDE_finish:
8173    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8174    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8175    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8177    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8178    GOTO_OPCODE(ip)                     @ jump to next instruction
8179
8180/* continuation for OP_APUT_WIDE */
8181
8182.LOP_APUT_WIDE_finish:
8183    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8184    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8186    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8187    GOTO_OPCODE(ip)                     @ jump to next instruction
8188
8189/* continuation for OP_APUT_OBJECT */
8190    /*
8191     * On entry:
8192     *  r1 = vBB (arrayObj)
8193     *  r9 = vAA (obj)
8194     *  r10 = offset into array (vBB + vCC * width)
8195     */
8196.LOP_APUT_OBJECT_finish:
8197    cmp     r9, #0                      @ storing null reference?
8198    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8199    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8200    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8201    bl      dvmCanPutArrayElement       @ test object type vs. array type
8202    cmp     r0, #0                      @ okay?
8203    beq     common_errArrayStore        @ no
8204.LOP_APUT_OBJECT_skip_check:
8205    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8207    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8208    GOTO_OPCODE(ip)                     @ jump to next instruction
8209
8210/* continuation for OP_IGET */
8211
8212    /*
8213     * Currently:
8214     *  r0 holds resolved field
8215     *  r9 holds object
8216     */
8217.LOP_IGET_finish:
8218    @bl      common_squeak0
8219    cmp     r9, #0                      @ check object for null
8220    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8221    beq     common_errNullObject        @ object was null
8222    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8223    ubfx    r2, rINST, #8, #4           @ r2<- A
8224    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8226    SET_VREG(r0, r2)                    @ fp[A]<- r0
8227    GOTO_OPCODE(ip)                     @ jump to next instruction
8228
8229/* continuation for OP_IGET_WIDE */
8230
8231    /*
8232     * Currently:
8233     *  r0 holds resolved field
8234     *  r9 holds object
8235     */
8236.LOP_IGET_WIDE_finish:
8237    cmp     r9, #0                      @ check object for null
8238    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8239    beq     common_errNullObject        @ object was null
8240    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8241    ubfx    r2, rINST, #8, #4           @ r2<- A
8242    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8243    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8244    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8245    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8246    GOTO_OPCODE(ip)                     @ jump to next instruction
8247
8248/* continuation for OP_IGET_OBJECT */
8249
8250    /*
8251     * Currently:
8252     *  r0 holds resolved field
8253     *  r9 holds object
8254     */
8255.LOP_IGET_OBJECT_finish:
8256    @bl      common_squeak0
8257    cmp     r9, #0                      @ check object for null
8258    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8259    beq     common_errNullObject        @ object was null
8260    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8261    @ no-op                             @ acquiring load
8262    mov     r2, rINST, lsr #8           @ r2<- A+
8263    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8264    and     r2, r2, #15                 @ r2<- A
8265    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8266    SET_VREG(r0, r2)                    @ fp[A]<- r0
8267    GOTO_OPCODE(ip)                     @ jump to next instruction
8268
8269/* continuation for OP_IGET_BOOLEAN */
8270
8271    /*
8272     * Currently:
8273     *  r0 holds resolved field
8274     *  r9 holds object
8275     */
8276.LOP_IGET_BOOLEAN_finish:
8277    @bl      common_squeak1
8278    cmp     r9, #0                      @ check object for null
8279    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8280    beq     common_errNullObject        @ object was null
8281    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8282    @ no-op                             @ acquiring load
8283    mov     r2, rINST, lsr #8           @ r2<- A+
8284    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8285    and     r2, r2, #15                 @ r2<- A
8286    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8287    SET_VREG(r0, r2)                    @ fp[A]<- r0
8288    GOTO_OPCODE(ip)                     @ jump to next instruction
8289
8290/* continuation for OP_IGET_BYTE */
8291
8292    /*
8293     * Currently:
8294     *  r0 holds resolved field
8295     *  r9 holds object
8296     */
8297.LOP_IGET_BYTE_finish:
8298    @bl      common_squeak2
8299    cmp     r9, #0                      @ check object for null
8300    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8301    beq     common_errNullObject        @ object was null
8302    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8303    @ no-op                             @ acquiring load
8304    mov     r2, rINST, lsr #8           @ r2<- A+
8305    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8306    and     r2, r2, #15                 @ r2<- A
8307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8308    SET_VREG(r0, r2)                    @ fp[A]<- r0
8309    GOTO_OPCODE(ip)                     @ jump to next instruction
8310
8311/* continuation for OP_IGET_CHAR */
8312
8313    /*
8314     * Currently:
8315     *  r0 holds resolved field
8316     *  r9 holds object
8317     */
8318.LOP_IGET_CHAR_finish:
8319    @bl      common_squeak3
8320    cmp     r9, #0                      @ check object for null
8321    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8322    beq     common_errNullObject        @ object was null
8323    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8324    @ no-op                             @ acquiring load
8325    mov     r2, rINST, lsr #8           @ r2<- A+
8326    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8327    and     r2, r2, #15                 @ r2<- A
8328    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8329    SET_VREG(r0, r2)                    @ fp[A]<- r0
8330    GOTO_OPCODE(ip)                     @ jump to next instruction
8331
8332/* continuation for OP_IGET_SHORT */
8333
8334    /*
8335     * Currently:
8336     *  r0 holds resolved field
8337     *  r9 holds object
8338     */
8339.LOP_IGET_SHORT_finish:
8340    @bl      common_squeak4
8341    cmp     r9, #0                      @ check object for null
8342    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8343    beq     common_errNullObject        @ object was null
8344    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8345    @ no-op                             @ acquiring load
8346    mov     r2, rINST, lsr #8           @ r2<- A+
8347    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8348    and     r2, r2, #15                 @ r2<- A
8349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8350    SET_VREG(r0, r2)                    @ fp[A]<- r0
8351    GOTO_OPCODE(ip)                     @ jump to next instruction
8352
8353/* continuation for OP_IPUT */
8354
8355    /*
8356     * Currently:
8357     *  r0 holds resolved field
8358     *  r9 holds object
8359     */
8360.LOP_IPUT_finish:
8361    @bl      common_squeak0
8362    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8363    ubfx    r1, rINST, #8, #4           @ r1<- A
8364    cmp     r9, #0                      @ check object for null
8365    GET_VREG(r0, r1)                    @ r0<- fp[A]
8366    beq     common_errNullObject        @ object was null
8367    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8369    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8370    GOTO_OPCODE(ip)                     @ jump to next instruction
8371
8372/* continuation for OP_IPUT_WIDE */
8373
8374    /*
8375     * Currently:
8376     *  r0 holds resolved field
8377     *  r9 holds object
8378     */
8379.LOP_IPUT_WIDE_finish:
8380    ubfx    r2, rINST, #8, #4           @ r2<- A
8381    cmp     r9, #0                      @ check object for null
8382    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8383    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8384    beq     common_errNullObject        @ object was null
8385    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8386    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8388    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8389    GOTO_OPCODE(ip)                     @ jump to next instruction
8390
8391/* continuation for OP_IPUT_OBJECT */
8392
8393    /*
8394     * Currently:
8395     *  r0 holds resolved field
8396     *  r9 holds object
8397     */
8398.LOP_IPUT_OBJECT_finish:
8399    @bl      common_squeak0
8400    mov     r1, rINST, lsr #8           @ r1<- A+
8401    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8402    and     r1, r1, #15                 @ r1<- A
8403    cmp     r9, #0                      @ check object for null
8404    GET_VREG(r0, r1)                    @ r0<- fp[A]
8405    beq     common_errNullObject        @ object was null
8406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8407    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8408    @ no-op                             @ releasing store
8409    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8410    GOTO_OPCODE(ip)                     @ jump to next instruction
8411
8412/* continuation for OP_IPUT_BOOLEAN */
8413
8414    /*
8415     * Currently:
8416     *  r0 holds resolved field
8417     *  r9 holds object
8418     */
8419.LOP_IPUT_BOOLEAN_finish:
8420    @bl      common_squeak1
8421    mov     r1, rINST, lsr #8           @ r1<- A+
8422    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8423    and     r1, r1, #15                 @ r1<- A
8424    cmp     r9, #0                      @ check object for null
8425    GET_VREG(r0, r1)                    @ r0<- fp[A]
8426    beq     common_errNullObject        @ object was null
8427    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8429    @ no-op                             @ releasing store
8430    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8431    GOTO_OPCODE(ip)                     @ jump to next instruction
8432
8433/* continuation for OP_IPUT_BYTE */
8434
8435    /*
8436     * Currently:
8437     *  r0 holds resolved field
8438     *  r9 holds object
8439     */
8440.LOP_IPUT_BYTE_finish:
8441    @bl      common_squeak2
8442    mov     r1, rINST, lsr #8           @ r1<- A+
8443    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8444    and     r1, r1, #15                 @ r1<- A
8445    cmp     r9, #0                      @ check object for null
8446    GET_VREG(r0, r1)                    @ r0<- fp[A]
8447    beq     common_errNullObject        @ object was null
8448    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8449    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8450    @ no-op                             @ releasing store
8451    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8452    GOTO_OPCODE(ip)                     @ jump to next instruction
8453
8454/* continuation for OP_IPUT_CHAR */
8455
8456    /*
8457     * Currently:
8458     *  r0 holds resolved field
8459     *  r9 holds object
8460     */
8461.LOP_IPUT_CHAR_finish:
8462    @bl      common_squeak3
8463    mov     r1, rINST, lsr #8           @ r1<- A+
8464    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8465    and     r1, r1, #15                 @ r1<- A
8466    cmp     r9, #0                      @ check object for null
8467    GET_VREG(r0, r1)                    @ r0<- fp[A]
8468    beq     common_errNullObject        @ object was null
8469    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8470    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8471    @ no-op                             @ releasing store
8472    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8473    GOTO_OPCODE(ip)                     @ jump to next instruction
8474
8475/* continuation for OP_IPUT_SHORT */
8476
8477    /*
8478     * Currently:
8479     *  r0 holds resolved field
8480     *  r9 holds object
8481     */
8482.LOP_IPUT_SHORT_finish:
8483    @bl      common_squeak4
8484    mov     r1, rINST, lsr #8           @ r1<- A+
8485    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8486    and     r1, r1, #15                 @ r1<- A
8487    cmp     r9, #0                      @ check object for null
8488    GET_VREG(r0, r1)                    @ r0<- fp[A]
8489    beq     common_errNullObject        @ object was null
8490    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8492    @ no-op                             @ releasing store
8493    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8494    GOTO_OPCODE(ip)                     @ jump to next instruction
8495
8496/* continuation for OP_SGET */
8497
8498    /*
8499     * Continuation if the field has not yet been resolved.
8500     *  r1: BBBB field ref
8501     */
8502.LOP_SGET_resolve:
8503    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8504    EXPORT_PC()                         @ resolve() could throw, so export now
8505    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8506    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8507    cmp     r0, #0                      @ success?
8508    bne     .LOP_SGET_finish          @ yes, finish
8509    b       common_exceptionThrown      @ no, handle exception
8510
8511/* continuation for OP_SGET_WIDE */
8512
8513    /*
8514     * Continuation if the field has not yet been resolved.
8515     *  r1: BBBB field ref
8516     *
8517     * Returns StaticField pointer in r0.
8518     */
8519.LOP_SGET_WIDE_resolve:
8520    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8521    EXPORT_PC()                         @ resolve() could throw, so export now
8522    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8523    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8524    cmp     r0, #0                      @ success?
8525    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8526    b       common_exceptionThrown      @ no, handle exception
8527
8528/* continuation for OP_SGET_OBJECT */
8529
8530    /*
8531     * Continuation if the field has not yet been resolved.
8532     *  r1: BBBB field ref
8533     */
8534.LOP_SGET_OBJECT_resolve:
8535    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8536    EXPORT_PC()                         @ resolve() could throw, so export now
8537    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8538    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8539    cmp     r0, #0                      @ success?
8540    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8541    b       common_exceptionThrown      @ no, handle exception
8542
8543/* continuation for OP_SGET_BOOLEAN */
8544
8545    /*
8546     * Continuation if the field has not yet been resolved.
8547     *  r1: BBBB field ref
8548     */
8549.LOP_SGET_BOOLEAN_resolve:
8550    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8551    EXPORT_PC()                         @ resolve() could throw, so export now
8552    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8553    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8554    cmp     r0, #0                      @ success?
8555    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8556    b       common_exceptionThrown      @ no, handle exception
8557
8558/* continuation for OP_SGET_BYTE */
8559
8560    /*
8561     * Continuation if the field has not yet been resolved.
8562     *  r1: BBBB field ref
8563     */
8564.LOP_SGET_BYTE_resolve:
8565    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8566    EXPORT_PC()                         @ resolve() could throw, so export now
8567    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8568    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8569    cmp     r0, #0                      @ success?
8570    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8571    b       common_exceptionThrown      @ no, handle exception
8572
8573/* continuation for OP_SGET_CHAR */
8574
8575    /*
8576     * Continuation if the field has not yet been resolved.
8577     *  r1: BBBB field ref
8578     */
8579.LOP_SGET_CHAR_resolve:
8580    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8581    EXPORT_PC()                         @ resolve() could throw, so export now
8582    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8583    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8584    cmp     r0, #0                      @ success?
8585    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8586    b       common_exceptionThrown      @ no, handle exception
8587
8588/* continuation for OP_SGET_SHORT */
8589
8590    /*
8591     * Continuation if the field has not yet been resolved.
8592     *  r1: BBBB field ref
8593     */
8594.LOP_SGET_SHORT_resolve:
8595    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8596    EXPORT_PC()                         @ resolve() could throw, so export now
8597    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8598    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8599    cmp     r0, #0                      @ success?
8600    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8601    b       common_exceptionThrown      @ no, handle exception
8602
8603/* continuation for OP_SPUT */
8604
8605    /*
8606     * Continuation if the field has not yet been resolved.
8607     *  r1: BBBB field ref
8608     */
8609.LOP_SPUT_resolve:
8610    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8611    EXPORT_PC()                         @ resolve() could throw, so export now
8612    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8613    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8614    cmp     r0, #0                      @ success?
8615    bne     .LOP_SPUT_finish          @ yes, finish
8616    b       common_exceptionThrown      @ no, handle exception
8617
8618/* continuation for OP_SPUT_WIDE */
8619
8620    /*
8621     * Continuation if the field has not yet been resolved.
8622     *  r1: BBBB field ref
8623     *  r9: &fp[AA]
8624     *
8625     * Returns StaticField pointer in r2.
8626     */
8627.LOP_SPUT_WIDE_resolve:
8628    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8629    EXPORT_PC()                         @ resolve() could throw, so export now
8630    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8631    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8632    cmp     r0, #0                      @ success?
8633    mov     r2, r0                      @ copy to r2
8634    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8635    b       common_exceptionThrown      @ no, handle exception
8636
8637/* continuation for OP_SPUT_OBJECT */
8638
8639    /*
8640     * Continuation if the field has not yet been resolved.
8641     *  r1: BBBB field ref
8642     */
8643.LOP_SPUT_OBJECT_resolve:
8644    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8645    EXPORT_PC()                         @ resolve() could throw, so export now
8646    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8647    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8648    cmp     r0, #0                      @ success?
8649    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8650    b       common_exceptionThrown      @ no, handle exception
8651
8652/* continuation for OP_SPUT_BOOLEAN */
8653
8654    /*
8655     * Continuation if the field has not yet been resolved.
8656     *  r1: BBBB field ref
8657     */
8658.LOP_SPUT_BOOLEAN_resolve:
8659    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8660    EXPORT_PC()                         @ resolve() could throw, so export now
8661    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8662    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8663    cmp     r0, #0                      @ success?
8664    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8665    b       common_exceptionThrown      @ no, handle exception
8666
8667/* continuation for OP_SPUT_BYTE */
8668
8669    /*
8670     * Continuation if the field has not yet been resolved.
8671     *  r1: BBBB field ref
8672     */
8673.LOP_SPUT_BYTE_resolve:
8674    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8675    EXPORT_PC()                         @ resolve() could throw, so export now
8676    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8677    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8678    cmp     r0, #0                      @ success?
8679    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8680    b       common_exceptionThrown      @ no, handle exception
8681
8682/* continuation for OP_SPUT_CHAR */
8683
8684    /*
8685     * Continuation if the field has not yet been resolved.
8686     *  r1: BBBB field ref
8687     */
8688.LOP_SPUT_CHAR_resolve:
8689    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8690    EXPORT_PC()                         @ resolve() could throw, so export now
8691    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8692    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8693    cmp     r0, #0                      @ success?
8694    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8695    b       common_exceptionThrown      @ no, handle exception
8696
8697/* continuation for OP_SPUT_SHORT */
8698
8699    /*
8700     * Continuation if the field has not yet been resolved.
8701     *  r1: BBBB field ref
8702     */
8703.LOP_SPUT_SHORT_resolve:
8704    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8705    EXPORT_PC()                         @ resolve() could throw, so export now
8706    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8707    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8708    cmp     r0, #0                      @ success?
8709    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8710    b       common_exceptionThrown      @ no, handle exception
8711
8712/* continuation for OP_INVOKE_VIRTUAL */
8713
8714    /*
8715     * At this point:
8716     *  r0 = resolved base method
8717     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8718     */
8719.LOP_INVOKE_VIRTUAL_continue:
8720    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8721    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8722    cmp     r1, #0                      @ is "this" null?
8723    beq     common_errNullObject        @ null "this", throw exception
8724    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8725    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8726    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8727    bl      common_invokeMethodNoRange @ continue on
8728
8729/* continuation for OP_INVOKE_SUPER */
8730
8731    /*
8732     * At this point:
8733     *  r0 = resolved base method
8734     *  r9 = method->clazz
8735     */
8736.LOP_INVOKE_SUPER_continue:
8737    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8738    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8739    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8740    EXPORT_PC()                         @ must export for invoke
8741    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8742    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8743    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8744    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8745    bl      common_invokeMethodNoRange @ continue on
8746
8747.LOP_INVOKE_SUPER_resolve:
8748    mov     r0, r9                      @ r0<- method->clazz
8749    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8750    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8751    cmp     r0, #0                      @ got null?
8752    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8753    b       common_exceptionThrown      @ yes, handle exception
8754
8755    /*
8756     * Throw a NoSuchMethodError with the method name as the message.
8757     *  r0 = resolved base method
8758     */
8759.LOP_INVOKE_SUPER_nsm:
8760    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8761    b       common_errNoSuchMethod
8762
8763/* continuation for OP_INVOKE_DIRECT */
8764
8765    /*
8766     * On entry:
8767     *  r1 = reference (BBBB or CCCC)
8768     *  r10 = "this" register
8769     */
8770.LOP_INVOKE_DIRECT_resolve:
8771    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8772    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8773    mov     r2, #METHOD_DIRECT          @ resolver method type
8774    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8775    cmp     r0, #0                      @ got null?
8776    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8777    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8778    b       common_exceptionThrown      @ yes, handle exception
8779
8780/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8781
8782    /*
8783     * At this point:
8784     *  r0 = resolved base method
8785     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8786     */
8787.LOP_INVOKE_VIRTUAL_RANGE_continue:
8788    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8789    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8790    cmp     r1, #0                      @ is "this" null?
8791    beq     common_errNullObject        @ null "this", throw exception
8792    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8793    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8794    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8795    bl      common_invokeMethodRange @ continue on
8796
8797/* continuation for OP_INVOKE_SUPER_RANGE */
8798
8799    /*
8800     * At this point:
8801     *  r0 = resolved base method
8802     *  r9 = method->clazz
8803     */
8804.LOP_INVOKE_SUPER_RANGE_continue:
8805    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8806    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8807    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8808    EXPORT_PC()                         @ must export for invoke
8809    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8810    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8811    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8812    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8813    bl      common_invokeMethodRange @ continue on
8814
8815.LOP_INVOKE_SUPER_RANGE_resolve:
8816    mov     r0, r9                      @ r0<- method->clazz
8817    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8818    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8819    cmp     r0, #0                      @ got null?
8820    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8821    b       common_exceptionThrown      @ yes, handle exception
8822
8823    /*
8824     * Throw a NoSuchMethodError with the method name as the message.
8825     *  r0 = resolved base method
8826     */
8827.LOP_INVOKE_SUPER_RANGE_nsm:
8828    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8829    b       common_errNoSuchMethod
8830
8831/* continuation for OP_INVOKE_DIRECT_RANGE */
8832
8833    /*
8834     * On entry:
8835     *  r1 = reference (BBBB or CCCC)
8836     *  r10 = "this" register
8837     */
8838.LOP_INVOKE_DIRECT_RANGE_resolve:
8839    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8840    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8841    mov     r2, #METHOD_DIRECT          @ resolver method type
8842    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8843    cmp     r0, #0                      @ got null?
8844    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8845    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8846    b       common_exceptionThrown      @ yes, handle exception
8847
8848/* continuation for OP_FLOAT_TO_LONG */
8849/*
8850 * Convert the float in r0 to a long in r0/r1.
8851 *
8852 * We have to clip values to long min/max per the specification.  The
8853 * expected common case is a "reasonable" value that converts directly
8854 * to modest integer.  The EABI convert function isn't doing this for us.
8855 */
8856f2l_doconv:
8857    stmfd   sp!, {r4, lr}
8858    mov     r1, #0x5f000000             @ (float)maxlong
8859    mov     r4, r0
8860    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8861    cmp     r0, #0                      @ nonzero == yes
8862    mvnne   r0, #0                      @ return maxlong (7fffffff)
8863    mvnne   r1, #0x80000000
8864    ldmnefd sp!, {r4, pc}
8865
8866    mov     r0, r4                      @ recover arg
8867    mov     r1, #0xdf000000             @ (float)minlong
8868    bl      __aeabi_fcmple              @ is arg <= minlong?
8869    cmp     r0, #0                      @ nonzero == yes
8870    movne   r0, #0                      @ return minlong (80000000)
8871    movne   r1, #0x80000000
8872    ldmnefd sp!, {r4, pc}
8873
8874    mov     r0, r4                      @ recover arg
8875    mov     r1, r4
8876    bl      __aeabi_fcmpeq              @ is arg == self?
8877    cmp     r0, #0                      @ zero == no
8878    moveq   r1, #0                      @ return zero for NaN
8879    ldmeqfd sp!, {r4, pc}
8880
8881    mov     r0, r4                      @ recover arg
8882    bl      __aeabi_f2lz                @ convert float to long
8883    ldmfd   sp!, {r4, pc}
8884
8885/* continuation for OP_DOUBLE_TO_LONG */
8886/*
8887 * Convert the double in r0/r1 to a long in r0/r1.
8888 *
8889 * We have to clip values to long min/max per the specification.  The
8890 * expected common case is a "reasonable" value that converts directly
8891 * to modest integer.  The EABI convert function isn't doing this for us.
8892 */
8893d2l_doconv:
8894    stmfd   sp!, {r4, r5, lr}           @ save regs
8895    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8896    add     r3, #0x00e00000             @  0x43e00000
8897    mov     r2, #0                      @ maxlong, as a double (low word)
8898    sub     sp, sp, #4                  @ align for EABI
8899    mov     r4, r0                      @ save a copy of r0
8900    mov     r5, r1                      @  and r1
8901    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8902    cmp     r0, #0                      @ nonzero == yes
8903    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8904    mvnne   r1, #0x80000000
8905    bne     1f
8906
8907    mov     r0, r4                      @ recover arg
8908    mov     r1, r5
8909    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8910    add     r3, #0x00e00000             @  0xc3e00000
8911    mov     r2, #0                      @ minlong, as a double (low word)
8912    bl      __aeabi_dcmple              @ is arg <= minlong?
8913    cmp     r0, #0                      @ nonzero == yes
8914    movne   r0, #0                      @ return minlong (8000000000000000)
8915    movne   r1, #0x80000000
8916    bne     1f
8917
8918    mov     r0, r4                      @ recover arg
8919    mov     r1, r5
8920    mov     r2, r4                      @ compare against self
8921    mov     r3, r5
8922    bl      __aeabi_dcmpeq              @ is arg == self?
8923    cmp     r0, #0                      @ zero == no
8924    moveq   r1, #0                      @ return zero for NaN
8925    beq     1f
8926
8927    mov     r0, r4                      @ recover arg
8928    mov     r1, r5
8929    bl      __aeabi_d2lz                @ convert double to long
8930
89311:
8932    add     sp, sp, #4
8933    ldmfd   sp!, {r4, r5, pc}
8934
8935/* continuation for OP_MUL_LONG */
8936
8937.LOP_MUL_LONG_finish:
8938    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8939    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8940    GOTO_OPCODE(ip)                     @ jump to next instruction
8941
8942/* continuation for OP_SHL_LONG */
8943
8944.LOP_SHL_LONG_finish:
8945    mov     r0, r0, asl r2              @  r0<- r0 << r2
8946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8947    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8948    GOTO_OPCODE(ip)                     @ jump to next instruction
8949
8950/* continuation for OP_SHR_LONG */
8951
8952.LOP_SHR_LONG_finish:
8953    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8955    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8956    GOTO_OPCODE(ip)                     @ jump to next instruction
8957
8958/* continuation for OP_USHR_LONG */
8959
8960.LOP_USHR_LONG_finish:
8961    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8962    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8963    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8964    GOTO_OPCODE(ip)                     @ jump to next instruction
8965
8966/* continuation for OP_SHL_LONG_2ADDR */
8967
8968.LOP_SHL_LONG_2ADDR_finish:
8969    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8970    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8971    GOTO_OPCODE(ip)                     @ jump to next instruction
8972
8973/* continuation for OP_SHR_LONG_2ADDR */
8974
8975.LOP_SHR_LONG_2ADDR_finish:
8976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8977    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8978    GOTO_OPCODE(ip)                     @ jump to next instruction
8979
8980/* continuation for OP_USHR_LONG_2ADDR */
8981
8982.LOP_USHR_LONG_2ADDR_finish:
8983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8984    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8985    GOTO_OPCODE(ip)                     @ jump to next instruction
8986
8987/* continuation for OP_IGET_VOLATILE */
8988
8989    /*
8990     * Currently:
8991     *  r0 holds resolved field
8992     *  r9 holds object
8993     */
8994.LOP_IGET_VOLATILE_finish:
8995    @bl      common_squeak0
8996    cmp     r9, #0                      @ check object for null
8997    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8998    beq     common_errNullObject        @ object was null
8999    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9000    SMP_DMB                            @ acquiring load
9001    mov     r2, rINST, lsr #8           @ r2<- A+
9002    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9003    and     r2, r2, #15                 @ r2<- A
9004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9005    SET_VREG(r0, r2)                    @ fp[A]<- r0
9006    GOTO_OPCODE(ip)                     @ jump to next instruction
9007
9008/* continuation for OP_IPUT_VOLATILE */
9009
9010    /*
9011     * Currently:
9012     *  r0 holds resolved field
9013     *  r9 holds object
9014     */
9015.LOP_IPUT_VOLATILE_finish:
9016    @bl      common_squeak0
9017    mov     r1, rINST, lsr #8           @ r1<- A+
9018    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9019    and     r1, r1, #15                 @ r1<- A
9020    cmp     r9, #0                      @ check object for null
9021    GET_VREG(r0, r1)                    @ r0<- fp[A]
9022    beq     common_errNullObject        @ object was null
9023    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9025    SMP_DMB                            @ releasing store
9026    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9027    GOTO_OPCODE(ip)                     @ jump to next instruction
9028
9029/* continuation for OP_SGET_VOLATILE */
9030
9031    /*
9032     * Continuation if the field has not yet been resolved.
9033     *  r1: BBBB field ref
9034     */
9035.LOP_SGET_VOLATILE_resolve:
9036    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9037    EXPORT_PC()                         @ resolve() could throw, so export now
9038    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9039    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9040    cmp     r0, #0                      @ success?
9041    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9042    b       common_exceptionThrown      @ no, handle exception
9043
9044/* continuation for OP_SPUT_VOLATILE */
9045
9046    /*
9047     * Continuation if the field has not yet been resolved.
9048     *  r1: BBBB field ref
9049     */
9050.LOP_SPUT_VOLATILE_resolve:
9051    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9052    EXPORT_PC()                         @ resolve() could throw, so export now
9053    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9054    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9055    cmp     r0, #0                      @ success?
9056    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9057    b       common_exceptionThrown      @ no, handle exception
9058
9059/* continuation for OP_IGET_OBJECT_VOLATILE */
9060
9061    /*
9062     * Currently:
9063     *  r0 holds resolved field
9064     *  r9 holds object
9065     */
9066.LOP_IGET_OBJECT_VOLATILE_finish:
9067    @bl      common_squeak0
9068    cmp     r9, #0                      @ check object for null
9069    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9070    beq     common_errNullObject        @ object was null
9071    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9072    SMP_DMB                            @ acquiring load
9073    mov     r2, rINST, lsr #8           @ r2<- A+
9074    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9075    and     r2, r2, #15                 @ r2<- A
9076    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9077    SET_VREG(r0, r2)                    @ fp[A]<- r0
9078    GOTO_OPCODE(ip)                     @ jump to next instruction
9079
9080/* continuation for OP_IGET_WIDE_VOLATILE */
9081
9082    /*
9083     * Currently:
9084     *  r0 holds resolved field
9085     *  r9 holds object
9086     */
9087.LOP_IGET_WIDE_VOLATILE_finish:
9088    cmp     r9, #0                      @ check object for null
9089    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9090    beq     common_errNullObject        @ object was null
9091    .if     1
9092    add     r0, r9, r3                  @ r0<- address of field
9093    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9094    .else
9095    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9096    .endif
9097    mov     r2, rINST, lsr #8           @ r2<- A+
9098    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9099    and     r2, r2, #15                 @ r2<- A
9100    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9102    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9103    GOTO_OPCODE(ip)                     @ jump to next instruction
9104
9105/* continuation for OP_IPUT_WIDE_VOLATILE */
9106
9107    /*
9108     * Currently:
9109     *  r0 holds resolved field
9110     *  r9 holds object
9111     */
9112.LOP_IPUT_WIDE_VOLATILE_finish:
9113    mov     r2, rINST, lsr #8           @ r2<- A+
9114    cmp     r9, #0                      @ check object for null
9115    and     r2, r2, #15                 @ r2<- A
9116    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9117    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9118    beq     common_errNullObject        @ object was null
9119    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9120    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9121    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9122    .if     1
9123    add     r2, r9, r3                  @ r2<- target address
9124    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9125    .else
9126    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9127    .endif
9128    GOTO_OPCODE(r10)                    @ jump to next instruction
9129
9130/* continuation for OP_SGET_WIDE_VOLATILE */
9131
9132    /*
9133     * Continuation if the field has not yet been resolved.
9134     *  r1: BBBB field ref
9135     *
9136     * Returns StaticField pointer in r0.
9137     */
9138.LOP_SGET_WIDE_VOLATILE_resolve:
9139    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9140    EXPORT_PC()                         @ resolve() could throw, so export now
9141    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9142    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9143    cmp     r0, #0                      @ success?
9144    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9145    b       common_exceptionThrown      @ no, handle exception
9146
9147/* continuation for OP_SPUT_WIDE_VOLATILE */
9148
9149    /*
9150     * Continuation if the field has not yet been resolved.
9151     *  r1: BBBB field ref
9152     *  r9: &fp[AA]
9153     *
9154     * Returns StaticField pointer in r2.
9155     */
9156.LOP_SPUT_WIDE_VOLATILE_resolve:
9157    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9158    EXPORT_PC()                         @ resolve() could throw, so export now
9159    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9160    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9161    cmp     r0, #0                      @ success?
9162    mov     r2, r0                      @ copy to r2
9163    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9164    b       common_exceptionThrown      @ no, handle exception
9165
9166/* continuation for OP_EXECUTE_INLINE */
9167
9168    /*
9169     * Extract args, call function.
9170     *  r0 = #of args (0-4)
9171     *  r10 = call index
9172     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9173     *
9174     * Other ideas:
9175     * - Use a jump table from the main piece to jump directly into the
9176     *   AND/LDR pairs.  Costs a data load, saves a branch.
9177     * - Have five separate pieces that do the loading, so we can work the
9178     *   interleave a little better.  Increases code size.
9179     */
9180.LOP_EXECUTE_INLINE_continue:
9181    rsb     r0, r0, #4                  @ r0<- 4-r0
9182    FETCH(r9, 2)                        @ r9<- FEDC
9183    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9184    bl      common_abort                @ (skipped due to ARM prefetch)
91854:  and     ip, r9, #0xf000             @ isolate F
9186    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
91873:  and     ip, r9, #0x0f00             @ isolate E
9188    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
91892:  and     ip, r9, #0x00f0             @ isolate D
9190    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
91911:  and     ip, r9, #0x000f             @ isolate C
9192    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
91930:
9194    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9195    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9196    @ (not reached)
9197
9198.LOP_EXECUTE_INLINE_table:
9199    .word   gDvmInlineOpsTable
9200
9201/* continuation for OP_EXECUTE_INLINE_RANGE */
9202
9203    /*
9204     * Extract args, call function.
9205     *  r0 = #of args (0-4)
9206     *  r10 = call index
9207     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9208     */
9209.LOP_EXECUTE_INLINE_RANGE_continue:
9210    rsb     r0, r0, #4                  @ r0<- 4-r0
9211    FETCH(r9, 2)                        @ r9<- CCCC
9212    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9213    bl      common_abort                @ (skipped due to ARM prefetch)
92144:  add     ip, r9, #3                  @ base+3
9215    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92163:  add     ip, r9, #2                  @ base+2
9217    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92182:  add     ip, r9, #1                  @ base+1
9219    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92201:  add     ip, r9, #0                  @ (nop)
9221    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92220:
9223    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9224    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9225    @ (not reached)
9226
9227.LOP_EXECUTE_INLINE_RANGE_table:
9228    .word   gDvmInlineOpsTable
9229
9230/* continuation for OP_IPUT_OBJECT_VOLATILE */
9231
9232    /*
9233     * Currently:
9234     *  r0 holds resolved field
9235     *  r9 holds object
9236     */
9237.LOP_IPUT_OBJECT_VOLATILE_finish:
9238    @bl      common_squeak0
9239    mov     r1, rINST, lsr #8           @ r1<- A+
9240    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9241    and     r1, r1, #15                 @ r1<- A
9242    cmp     r9, #0                      @ check object for null
9243    GET_VREG(r0, r1)                    @ r0<- fp[A]
9244    beq     common_errNullObject        @ object was null
9245    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9246    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9247    SMP_DMB                            @ releasing store
9248    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9249    GOTO_OPCODE(ip)                     @ jump to next instruction
9250
9251/* continuation for OP_SGET_OBJECT_VOLATILE */
9252
9253    /*
9254     * Continuation if the field has not yet been resolved.
9255     *  r1: BBBB field ref
9256     */
9257.LOP_SGET_OBJECT_VOLATILE_resolve:
9258    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9259    EXPORT_PC()                         @ resolve() could throw, so export now
9260    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9261    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9262    cmp     r0, #0                      @ success?
9263    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9264    b       common_exceptionThrown      @ no, handle exception
9265
9266/* continuation for OP_SPUT_OBJECT_VOLATILE */
9267
9268    /*
9269     * Continuation if the field has not yet been resolved.
9270     *  r1: BBBB field ref
9271     */
9272.LOP_SPUT_OBJECT_VOLATILE_resolve:
9273    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9274    EXPORT_PC()                         @ resolve() could throw, so export now
9275    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9276    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9277    cmp     r0, #0                      @ success?
9278    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
9279    b       common_exceptionThrown      @ no, handle exception
9280
9281    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9282    .global dvmAsmSisterEnd
9283dvmAsmSisterEnd:
9284
9285/* File: armv5te/footer.S */
9286
9287/*
9288 * ===========================================================================
9289 *  Common subroutines and data
9290 * ===========================================================================
9291 */
9292
9293
9294
9295    .text
9296    .align  2
9297
9298#if defined(WITH_JIT)
9299#if defined(WITH_SELF_VERIFICATION)
9300    .global dvmJitToInterpPunt
9301dvmJitToInterpPunt:
9302    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9303    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9304    mov    r3, #0
9305    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9306    b      jitSVShadowRunEnd            @ doesn't return
9307
9308    .global dvmJitToInterpSingleStep
9309dvmJitToInterpSingleStep:
9310    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9311    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9312    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9313    b      jitSVShadowRunEnd            @ doesn't return
9314
9315    .global dvmJitToInterpTraceSelectNoChain
9316dvmJitToInterpTraceSelectNoChain:
9317    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9318    mov    r0,rPC                       @ pass our target PC
9319    mov    r2,#kSVSTraceSelectNoChain   @ r2<- interpreter entry point
9320    mov    r3, #0
9321    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9322    b      jitSVShadowRunEnd            @ doesn't return
9323
9324    .global dvmJitToInterpTraceSelect
9325dvmJitToInterpTraceSelect:
9326    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9327    ldr    r0,[lr, #-1]                 @ pass our target PC
9328    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9329    mov    r3, #0
9330    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9331    b      jitSVShadowRunEnd            @ doesn't return
9332
9333    .global dvmJitToInterpBackwardBranch
9334dvmJitToInterpBackwardBranch:
9335    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9336    ldr    r0,[lr, #-1]                 @ pass our target PC
9337    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9338    mov    r3, #0
9339    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9340    b      jitSVShadowRunEnd            @ doesn't return
9341
9342    .global dvmJitToInterpNormal
9343dvmJitToInterpNormal:
9344    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9345    ldr    r0,[lr, #-1]                 @ pass our target PC
9346    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9347    mov    r3, #0
9348    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9349    b      jitSVShadowRunEnd            @ doesn't return
9350
9351    .global dvmJitToInterpNoChain
9352dvmJitToInterpNoChain:
9353    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9354    mov    r0,rPC                       @ pass our target PC
9355    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9356    mov    r3, #0
9357    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9358    b      jitSVShadowRunEnd            @ doesn't return
9359#else
9360/*
9361 * Return from the translation cache to the interpreter when the compiler is
9362 * having issues translating/executing a Dalvik instruction. We have to skip
9363 * the code cache lookup otherwise it is possible to indefinitely bouce
9364 * between the interpreter and the code cache if the instruction that fails
9365 * to be compiled happens to be at a trace start.
9366 */
9367    .global dvmJitToInterpPunt
9368dvmJitToInterpPunt:
9369    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9370    mov    rPC, r0
9371#if defined(WITH_JIT_TUNING)
9372    mov    r0,lr
9373    bl     dvmBumpPunt;
9374#endif
9375    EXPORT_PC()
9376    mov    r0, #0
9377    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9378    adrl   rIBASE, dvmAsmInstructionStart
9379    FETCH_INST()
9380    GET_INST_OPCODE(ip)
9381    GOTO_OPCODE(ip)
9382
9383/*
9384 * Return to the interpreter to handle a single instruction.
9385 * On entry:
9386 *    r0 <= PC
9387 *    r1 <= PC of resume instruction
9388 *    lr <= resume point in translation
9389 */
9390    .global dvmJitToInterpSingleStep
9391dvmJitToInterpSingleStep:
9392    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9393    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9394    mov    r1,#kInterpEntryInstr
9395    @ enum is 4 byte in aapcs-EABI
9396    str    r1, [rGLUE, #offGlue_entryPoint]
9397    mov    rPC,r0
9398    EXPORT_PC()
9399
9400    adrl   rIBASE, dvmAsmInstructionStart
9401    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9402    str    r2,[rGLUE,#offGlue_jitState]
9403    mov    r1,#1                  @ set changeInterp to bail to debug interp
9404    b      common_gotoBail
9405
9406/*
9407 * Return from the translation cache and immediately request
9408 * a translation for the exit target.  Commonly used for callees.
9409 */
9410    .global dvmJitToInterpTraceSelectNoChain
9411dvmJitToInterpTraceSelectNoChain:
9412#if defined(WITH_JIT_TUNING)
9413    bl     dvmBumpNoChain
9414#endif
9415    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9416    mov    r0,rPC
9417    bl     dvmJitGetCodeAddr        @ Is there a translation?
9418    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9419    mov    r1, rPC                  @ arg1 of translation may need this
9420    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9421    cmp    r0,#0
9422    bxne   r0                       @ continue native execution if so
9423    b      2f
9424
9425/*
9426 * Return from the translation cache and immediately request
9427 * a translation for the exit target.  Commonly used following
9428 * invokes.
9429 */
9430    .global dvmJitToInterpTraceSelect
9431dvmJitToInterpTraceSelect:
9432    ldr    rPC,[lr, #-1]           @ get our target PC
9433    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9434    add    rINST,lr,#-5            @ save start of chain branch
9435    add    rINST, #-4              @  .. which is 9 bytes back
9436    mov    r0,rPC
9437    bl     dvmJitGetCodeAddr       @ Is there a translation?
9438    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9439    cmp    r0,#0
9440    beq    2f
9441    mov    r1,rINST
9442    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9443    mov    r1, rPC                  @ arg1 of translation may need this
9444    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9445    cmp    r0,#0                    @ successful chain?
9446    bxne   r0                       @ continue native execution
9447    b      toInterpreter            @ didn't chain - resume with interpreter
9448
9449/* No translation, so request one if profiling isn't disabled*/
94502:
9451    adrl   rIBASE, dvmAsmInstructionStart
9452    GET_JIT_PROF_TABLE(r0)
9453    FETCH_INST()
9454    cmp    r0, #0
9455    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9456    bne    common_selectTrace
9457    GET_INST_OPCODE(ip)
9458    GOTO_OPCODE(ip)
9459
9460/*
9461 * Return from the translation cache to the interpreter.
9462 * The return was done with a BLX from thumb mode, and
9463 * the following 32-bit word contains the target rPC value.
9464 * Note that lr (r14) will have its low-order bit set to denote
9465 * its thumb-mode origin.
9466 *
9467 * We'll need to stash our lr origin away, recover the new
9468 * target and then check to see if there is a translation available
9469 * for our new target.  If so, we do a translation chain and
9470 * go back to native execution.  Otherwise, it's back to the
9471 * interpreter (after treating this entry as a potential
9472 * trace start).
9473 */
9474    .global dvmJitToInterpNormal
9475dvmJitToInterpNormal:
9476    ldr    rPC,[lr, #-1]           @ get our target PC
9477    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9478    add    rINST,lr,#-5            @ save start of chain branch
9479    add    rINST,#-4               @ .. which is 9 bytes back
9480#if defined(WITH_JIT_TUNING)
9481    bl     dvmBumpNormal
9482#endif
9483    mov    r0,rPC
9484    bl     dvmJitGetCodeAddr        @ Is there a translation?
9485    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9486    cmp    r0,#0
9487    beq    toInterpreter            @ go if not, otherwise do chain
9488    mov    r1,rINST
9489    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9490    mov    r1, rPC                  @ arg1 of translation may need this
9491    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9492    cmp    r0,#0                    @ successful chain?
9493    bxne   r0                       @ continue native execution
9494    b      toInterpreter            @ didn't chain - resume with interpreter
9495
9496/*
9497 * Return from the translation cache to the interpreter to do method invocation.
9498 * Check if translation exists for the callee, but don't chain to it.
9499 */
9500    .global dvmJitToInterpNoChain
9501dvmJitToInterpNoChain:
9502#if defined(WITH_JIT_TUNING)
9503    bl     dvmBumpNoChain
9504#endif
9505    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9506    mov    r0,rPC
9507    bl     dvmJitGetCodeAddr        @ Is there a translation?
9508    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9509    mov    r1, rPC                  @ arg1 of translation may need this
9510    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9511    cmp    r0,#0
9512    bxne   r0                       @ continue native execution if so
9513#endif
9514
9515/*
9516 * No translation, restore interpreter regs and start interpreting.
9517 * rGLUE & rFP were preserved in the translated code, and rPC has
9518 * already been restored by the time we get here.  We'll need to set
9519 * up rIBASE & rINST, and load the address of the JitTable into r0.
9520 */
9521toInterpreter:
9522    EXPORT_PC()
9523    adrl   rIBASE, dvmAsmInstructionStart
9524    FETCH_INST()
9525    GET_JIT_PROF_TABLE(r0)
9526    @ NOTE: intended fallthrough
9527/*
9528 * Common code to update potential trace start counter, and initiate
9529 * a trace-build if appropriate.  On entry, rPC should point to the
9530 * next instruction to execute, and rINST should be already loaded with
9531 * the next opcode word, and r0 holds a pointer to the jit profile
9532 * table (pJitProfTable).
9533 */
9534common_testUpdateProfile:
9535    cmp     r0,#0
9536    GET_INST_OPCODE(ip)
9537    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9538
9539common_updateProfile:
9540    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9541    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9542    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9543    GET_INST_OPCODE(ip)
9544    subs    r1,r1,#1           @ decrement counter
9545    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9546    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9547
9548/*
9549 * Here, we switch to the debug interpreter to request
9550 * trace selection.  First, though, check to see if there
9551 * is already a native translation in place (and, if so,
9552 * jump to it now).
9553 */
9554    GET_JIT_THRESHOLD(r1)
9555    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9556    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9557    EXPORT_PC()
9558    mov     r0,rPC
9559    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9560    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9561    mov     r1, rPC                     @ arg1 of translation may need this
9562    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9563    cmp     r0,#0
9564#if !defined(WITH_SELF_VERIFICATION)
9565    bxne    r0                          @ jump to the translation
9566    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9567    @ fall-through to common_selectTrace
9568#else
9569    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9570    beq     common_selectTrace
9571    /*
9572     * At this point, we have a target translation.  However, if
9573     * that translation is actually the interpret-only pseudo-translation
9574     * we want to treat it the same as no translation.
9575     */
9576    mov     r10, r0                     @ save target
9577    bl      dvmCompilerGetInterpretTemplate
9578    cmp     r0, r10                     @ special case?
9579    bne     jitSVShadowRunStart         @ set up self verification shadow space
9580    GET_INST_OPCODE(ip)
9581    GOTO_OPCODE(ip)
9582    /* no return */
9583#endif
9584
9585/*
9586 * On entry:
9587 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9588 */
9589common_selectTrace:
9590    str     r2,[rGLUE,#offGlue_jitState]
9591    mov     r2,#kInterpEntryInstr       @ normal entry reason
9592    str     r2,[rGLUE,#offGlue_entryPoint]
9593    mov     r1,#1                       @ set changeInterp
9594    b       common_gotoBail
9595
9596#if defined(WITH_SELF_VERIFICATION)
9597/*
9598 * Save PC and registers to shadow memory for self verification mode
9599 * before jumping to native translation.
9600 * On entry:
9601 *    rPC, rFP, rGLUE: the values that they should contain
9602 *    r10: the address of the target translation.
9603 */
9604jitSVShadowRunStart:
9605    mov     r0,rPC                      @ r0<- program counter
9606    mov     r1,rFP                      @ r1<- frame pointer
9607    mov     r2,rGLUE                    @ r2<- InterpState pointer
9608    mov     r3,r10                      @ r3<- target translation
9609    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9610    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9611    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9612    bx      r10                         @ jump to the translation
9613
9614/*
9615 * Restore PC, registers, and interpState to original values
9616 * before jumping back to the interpreter.
9617 */
9618jitSVShadowRunEnd:
9619    mov    r1,rFP                        @ pass ending fp
9620    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9621    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9622    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9623    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9624    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9625    cmp    r1,#0                         @ check for punt condition
9626    beq    1f
9627    mov    r2,#kJitSelfVerification      @ ask for self verification
9628    str    r2,[rGLUE,#offGlue_jitState]
9629    mov    r2,#kInterpEntryInstr         @ normal entry reason
9630    str    r2,[rGLUE,#offGlue_entryPoint]
9631    mov    r1,#1                         @ set changeInterp
9632    b      common_gotoBail
9633
96341:                                       @ exit to interpreter without check
9635    EXPORT_PC()
9636    adrl   rIBASE, dvmAsmInstructionStart
9637    FETCH_INST()
9638    GET_INST_OPCODE(ip)
9639    GOTO_OPCODE(ip)
9640#endif
9641
9642#endif
9643
9644/*
9645 * Common code when a backward branch is taken.
9646 *
9647 * TODO: we could avoid a branch by just setting r0 and falling through
9648 * into the common_periodicChecks code, and having a test on r0 at the
9649 * end determine if we should return to the caller or update & branch to
9650 * the next instr.
9651 *
9652 * On entry:
9653 *  r9 is PC adjustment *in bytes*
9654 */
9655common_backwardBranch:
9656    mov     r0, #kInterpEntryInstr
9657    bl      common_periodicChecks
9658#if defined(WITH_JIT)
9659    GET_JIT_PROF_TABLE(r0)
9660    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9661    cmp     r0,#0
9662    bne     common_updateProfile
9663    GET_INST_OPCODE(ip)
9664    GOTO_OPCODE(ip)
9665#else
9666    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9668    GOTO_OPCODE(ip)                     @ jump to next instruction
9669#endif
9670
9671
9672/*
9673 * Need to see if the thread needs to be suspended or debugger/profiler
9674 * activity has begun.  If so, we suspend the thread or side-exit to
9675 * the debug interpreter as appropriate.
9676 *
9677 * The common case is no activity on any of these, so we want to figure
9678 * that out quickly.  If something is up, we can then sort out what.
9679 *
9680 * We want to be fast if the VM was built without debugger or profiler
9681 * support, but we also need to recognize that the system is usually
9682 * shipped with both of these enabled.
9683 *
9684 * TODO: reduce this so we're just checking a single location.
9685 *
9686 * On entry:
9687 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9688 *  r9 is trampoline PC adjustment *in bytes*
9689 */
9690common_periodicChecks:
9691    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9692
9693#if defined(WITH_DEBUGGER)
9694    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9695#endif
9696#if defined(WITH_PROFILER)
9697    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9698#endif
9699
9700    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9701
9702#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9703    cmp     r1, #0                      @ debugger enabled?
9704    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9705    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9706    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9707    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9708#elif defined(WITH_DEBUGGER)
9709    cmp     r1, #0                      @ debugger enabled?
9710    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9711    orrsne  ip, ip, r1                  @ yes, ip<- suspend | debugger; set Z
9712    @ (if not enabled, Z was set by test for r1==0, which is what we want)
9713#elif defined (WITH_PROFILER)
9714    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9715    orrs    ip, ip, r2                  @ ip<- suspendCount | activeProfilers
9716#else
9717    cmp     ip, #0                      @ not ORing anything in; set Z
9718#endif
9719
9720    bxeq    lr                          @ all zero, return
9721
9722    /*
9723     * One or more interesting events have happened.  Figure out what.
9724     *
9725     * If debugging or profiling are compiled in, we need to disambiguate.
9726     *
9727     * r0 still holds the reentry type.
9728     */
9729#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9730    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9731    cmp     ip, #0                      @ want suspend?
9732    beq     1f                          @ no, must be debugger/profiler
9733#endif
9734
9735    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9736#if defined(WITH_JIT)
9737    /*
9738     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9739     * doubles as the Jit's on/off switch.
9740     */
9741    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9742    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9743    ldr     r3, [r3] @ r3 <- pJitProfTable
9744    EXPORT_PC()                         @ need for precise GC
9745    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9746#else
9747    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9748    EXPORT_PC()                         @ need for precise GC
9749#endif
9750    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9751    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9752
9753#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9754
9755    /*
9756     * Reload the debugger/profiler enable flags.  We're checking to see
9757     * if either of these got set while we were suspended.
9758     *
9759     * We can't really avoid the #ifdefs here, because the fields don't
9760     * exist when the feature is disabled.
9761     */
9762#if defined(WITH_DEBUGGER)
9763    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9764    cmp     r1, #0                      @ debugger enabled?
9765    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9766#else
9767    mov     r1, #0
9768#endif
9769#if defined(WITH_PROFILER)
9770    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9771    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9772#else
9773    mov     r2, #0
9774#endif
9775
9776    orrs    r1, r1, r2
9777    beq     2f
9778
97791:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9780    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9781    add     rPC, rPC, r9                @ update rPC
9782    mov     r1, #1                      @ "want switch" = true
9783    b       common_gotoBail             @ side exit
9784
9785#endif /*WITH_DEBUGGER || WITH_PROFILER*/
9786
97872:
9788    bx      lr                          @ nothing to do, return
9789
9790
9791/*
9792 * The equivalent of "goto bail", this calls through the "bail handler".
9793 *
9794 * State registers will be saved to the "glue" area before bailing.
9795 *
9796 * On entry:
9797 *  r1 is "bool changeInterp", indicating if we want to switch to the
9798 *     other interpreter or just bail all the way out
9799 */
9800common_gotoBail:
9801    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9802    mov     r0, rGLUE                   @ r0<- glue ptr
9803    b       dvmMterpStdBail             @ call(glue, changeInterp)
9804
9805    @add     r1, r1, #1                  @ using (boolean+1)
9806    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9807    @bl      _longjmp                    @ does not return
9808    @bl      common_abort
9809
9810
9811/*
9812 * Common code for method invocation with range.
9813 *
9814 * On entry:
9815 *  r0 is "Method* methodToCall", the method we're trying to call
9816 */
9817common_invokeMethodRange:
9818.LinvokeNewRange:
9819    @ prepare to copy args to "outs" area of current frame
9820    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9821    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9822    beq     .LinvokeArgsDone            @ if no args, skip the rest
9823    FETCH(r1, 2)                        @ r1<- CCCC
9824
9825    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9826    @ (very few methods have > 10 args; could unroll for common cases)
9827    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9828    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9829    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
98301:  ldr     r1, [r3], #4                @ val = *fp++
9831    subs    r2, r2, #1                  @ count--
9832    str     r1, [r10], #4               @ *outs++ = val
9833    bne     1b                          @ ...while count != 0
9834    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9835    b       .LinvokeArgsDone
9836
9837/*
9838 * Common code for method invocation without range.
9839 *
9840 * On entry:
9841 *  r0 is "Method* methodToCall", the method we're trying to call
9842 */
9843common_invokeMethodNoRange:
9844.LinvokeNewNoRange:
9845    @ prepare to copy args to "outs" area of current frame
9846    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9847    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9848    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9849    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9850    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9851    beq     .LinvokeArgsDone
9852
9853    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9854.LinvokeNonRange:
9855    rsb     r2, r2, #5                  @ r2<- 5-r2
9856    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9857    bl      common_abort                @ (skipped due to ARM prefetch)
98585:  and     ip, rINST, #0x0f00          @ isolate A
9859    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9860    mov     r0, r0                      @ nop
9861    str     r2, [r10, #-4]!             @ *--outs = vA
98624:  and     ip, r1, #0xf000             @ isolate G
9863    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9864    mov     r0, r0                      @ nop
9865    str     r2, [r10, #-4]!             @ *--outs = vG
98663:  and     ip, r1, #0x0f00             @ isolate F
9867    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9868    mov     r0, r0                      @ nop
9869    str     r2, [r10, #-4]!             @ *--outs = vF
98702:  and     ip, r1, #0x00f0             @ isolate E
9871    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9872    mov     r0, r0                      @ nop
9873    str     r2, [r10, #-4]!             @ *--outs = vE
98741:  and     ip, r1, #0x000f             @ isolate D
9875    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9876    mov     r0, r0                      @ nop
9877    str     r2, [r10, #-4]!             @ *--outs = vD
98780:  @ fall through to .LinvokeArgsDone
9879
9880.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9881    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9882    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9883    @ find space for the new stack frame, check for overflow
9884    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9885    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9886    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9887@    bl      common_dumpRegs
9888    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9889    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9890    cmp     r3, r9                      @ bottom < interpStackEnd?
9891    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9892    blo     .LstackOverflow             @ yes, this frame will overflow stack
9893
9894    @ set up newSaveArea
9895#ifdef EASY_GDB
9896    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9897    str     ip, [r10, #offStackSaveArea_prevSave]
9898#endif
9899    str     rFP, [r10, #offStackSaveArea_prevFrame]
9900    str     rPC, [r10, #offStackSaveArea_savedPc]
9901#if defined(WITH_JIT)
9902    mov     r9, #0
9903    str     r9, [r10, #offStackSaveArea_returnAddr]
9904#endif
9905    str     r0, [r10, #offStackSaveArea_method]
9906    tst     r3, #ACC_NATIVE
9907    bne     .LinvokeNative
9908
9909    /*
9910    stmfd   sp!, {r0-r3}
9911    bl      common_printNewline
9912    mov     r0, rFP
9913    mov     r1, #0
9914    bl      dvmDumpFp
9915    ldmfd   sp!, {r0-r3}
9916    stmfd   sp!, {r0-r3}
9917    mov     r0, r1
9918    mov     r1, r10
9919    bl      dvmDumpFp
9920    bl      common_printNewline
9921    ldmfd   sp!, {r0-r3}
9922    */
9923
9924    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9925    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9926    mov     rPC, r2                         @ publish new rPC
9927    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9928
9929    @ Update "glue" values for the new method
9930    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9931    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9932    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9933#if defined(WITH_JIT)
9934    GET_JIT_PROF_TABLE(r0)
9935    mov     rFP, r1                         @ fp = newFp
9936    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9937    mov     rINST, r9                       @ publish new rINST
9938    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9939    cmp     r0,#0
9940    bne     common_updateProfile
9941    GOTO_OPCODE(ip)                         @ jump to next instruction
9942#else
9943    mov     rFP, r1                         @ fp = newFp
9944    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9945    mov     rINST, r9                       @ publish new rINST
9946    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9947    GOTO_OPCODE(ip)                         @ jump to next instruction
9948#endif
9949
9950.LinvokeNative:
9951    @ Prep for the native call
9952    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9953    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9954    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9955    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9956    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9957    mov     r9, r3                      @ r9<- glue->self (preserve)
9958
9959    mov     r2, r0                      @ r2<- methodToCall
9960    mov     r0, r1                      @ r0<- newFp (points to args)
9961    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9962
9963#ifdef ASSIST_DEBUGGER
9964    /* insert fake function header to help gdb find the stack frame */
9965    b       .Lskip
9966    .type   dalvik_mterp, %function
9967dalvik_mterp:
9968    .fnstart
9969    MTERP_ENTRY1
9970    MTERP_ENTRY2
9971.Lskip:
9972#endif
9973
9974    @mov     lr, pc                      @ set return addr
9975    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9976    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9977
9978#if defined(WITH_JIT)
9979    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9980#endif
9981
9982    @ native return; r9=self, r10=newSaveArea
9983    @ equivalent to dvmPopJniLocals
9984    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9985    ldr     r1, [r9, #offThread_exception] @ check for exception
9986#if defined(WITH_JIT)
9987    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9988#endif
9989    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9990    cmp     r1, #0                      @ null?
9991    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9992#if defined(WITH_JIT)
9993    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9994#endif
9995    bne     common_exceptionThrown      @ no, handle exception
9996
9997    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9999    GOTO_OPCODE(ip)                     @ jump to next instruction
10000
10001.LstackOverflow:    @ r0=methodToCall
10002    mov     r1, r0                      @ r1<- methodToCall
10003    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10004    bl      dvmHandleStackOverflow
10005    b       common_exceptionThrown
10006#ifdef ASSIST_DEBUGGER
10007    .fnend
10008#endif
10009
10010
10011    /*
10012     * Common code for method invocation, calling through "glue code".
10013     *
10014     * TODO: now that we have range and non-range invoke handlers, this
10015     *       needs to be split into two.  Maybe just create entry points
10016     *       that set r9 and jump here?
10017     *
10018     * On entry:
10019     *  r0 is "Method* methodToCall", the method we're trying to call
10020     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10021     */
10022     .if    0
10023.LinvokeOld:
10024    sub     sp, sp, #8                  @ space for args + pad
10025    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10026    mov     r2, r0                      @ A2<- methodToCall
10027    mov     r0, rGLUE                   @ A0<- glue
10028    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10029    mov     r1, r9                      @ A1<- methodCallRange
10030    mov     r3, rINST, lsr #8           @ A3<- AA
10031    str     ip, [sp, #0]                @ A4<- ip
10032    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10033    add     sp, sp, #8                  @ remove arg area
10034    b       common_resumeAfterGlueCall  @ continue to next instruction
10035    .endif
10036
10037
10038
10039/*
10040 * Common code for handling a return instruction.
10041 *
10042 * This does not return.
10043 */
10044common_returnFromMethod:
10045.LreturnNew:
10046    mov     r0, #kInterpEntryReturn
10047    mov     r9, #0
10048    bl      common_periodicChecks
10049
10050    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10051    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10052    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10053    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10054                                        @ r2<- method we're returning to
10055    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10056    cmp     r2, #0                      @ is this a break frame?
10057    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10058    mov     r1, #0                      @ "want switch" = false
10059    beq     common_gotoBail             @ break frame, bail out completely
10060
10061    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10062    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10063    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10064    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10065#if defined(WITH_JIT)
10066    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10067    GET_JIT_PROF_TABLE(r0)
10068    mov     rPC, r9                     @ publish new rPC
10069    str     r1, [rGLUE, #offGlue_methodClassDex]
10070    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10071    cmp     r10, #0                      @ caller is compiled code
10072    blxne   r10
10073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10074    cmp     r0,#0
10075    bne     common_updateProfile
10076    GOTO_OPCODE(ip)                     @ jump to next instruction
10077#else
10078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10079    mov     rPC, r9                     @ publish new rPC
10080    str     r1, [rGLUE, #offGlue_methodClassDex]
10081    GOTO_OPCODE(ip)                     @ jump to next instruction
10082#endif
10083
10084    /*
10085     * Return handling, calls through "glue code".
10086     */
10087     .if    0
10088.LreturnOld:
10089    SAVE_PC_FP_TO_GLUE()                @ export state
10090    mov     r0, rGLUE                   @ arg to function
10091    bl      dvmMterp_returnFromMethod
10092    b       common_resumeAfterGlueCall
10093    .endif
10094
10095
10096/*
10097 * Somebody has thrown an exception.  Handle it.
10098 *
10099 * If the exception processing code returns to us (instead of falling
10100 * out of the interpreter), continue with whatever the next instruction
10101 * now happens to be.
10102 *
10103 * This does not return.
10104 */
10105     .global dvmMterpCommonExceptionThrown
10106dvmMterpCommonExceptionThrown:
10107common_exceptionThrown:
10108.LexceptionNew:
10109    mov     r0, #kInterpEntryThrow
10110    mov     r9, #0
10111    bl      common_periodicChecks
10112
10113    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10114    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10115    mov     r1, r10                     @ r1<- self
10116    mov     r0, r9                      @ r0<- exception
10117    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10118    mov     r3, #0                      @ r3<- NULL
10119    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10120
10121    /* set up args and a local for "&fp" */
10122    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10123    str     rFP, [sp, #-4]!             @ *--sp = fp
10124    mov     ip, sp                      @ ip<- &fp
10125    mov     r3, #0                      @ r3<- false
10126    str     ip, [sp, #-4]!              @ *--sp = &fp
10127    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10128    mov     r0, r10                     @ r0<- self
10129    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10130    mov     r2, r9                      @ r2<- exception
10131    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10132    mov     r1, r1, asr #1              @ r1<- offset in code units
10133
10134    /* call, r0 gets catchRelPc (a code-unit offset) */
10135    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10136
10137    /* fix earlier stack overflow if necessary; may trash rFP */
10138    ldrb    r1, [r10, #offThread_stackOverflowed]
10139    cmp     r1, #0                      @ did we overflow earlier?
10140    beq     1f                          @ no, skip ahead
10141    mov     rFP, r0                     @ save relPc result in rFP
10142    mov     r0, r10                     @ r0<- self
10143    mov     r1, r9                      @ r1<- exception
10144    bl      dvmCleanupStackOverflow     @ call(self)
10145    mov     r0, rFP                     @ restore result
101461:
10147
10148    /* update frame pointer and check result from dvmFindCatchBlock */
10149    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10150    cmp     r0, #0                      @ is catchRelPc < 0?
10151    add     sp, sp, #8                  @ restore stack
10152    bmi     .LnotCaughtLocally
10153
10154    /* adjust locals to match self->curFrame and updated PC */
10155    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10156    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10157    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10158    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10159    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10160    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10161    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10162    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10163
10164    /* release the tracked alloc on the exception */
10165    mov     r0, r9                      @ r0<- exception
10166    mov     r1, r10                     @ r1<- self
10167    bl      dvmReleaseTrackedAlloc      @ release the exception
10168
10169    /* restore the exception if the handler wants it */
10170    FETCH_INST()                        @ load rINST from rPC
10171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10172    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10173    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10174    GOTO_OPCODE(ip)                     @ jump to next instruction
10175
10176.LnotCaughtLocally: @ r9=exception, r10=self
10177    /* fix stack overflow if necessary */
10178    ldrb    r1, [r10, #offThread_stackOverflowed]
10179    cmp     r1, #0                      @ did we overflow earlier?
10180    movne   r0, r10                     @ if yes: r0<- self
10181    movne   r1, r9                      @ if yes: r1<- exception
10182    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10183
10184    @ may want to show "not caught locally" debug messages here
10185#if DVM_SHOW_EXCEPTION >= 2
10186    /* call __android_log_print(prio, tag, format, ...) */
10187    /* "Exception %s from %s:%d not caught locally" */
10188    @ dvmLineNumFromPC(method, pc - method->insns)
10189    ldr     r0, [rGLUE, #offGlue_method]
10190    ldr     r1, [r0, #offMethod_insns]
10191    sub     r1, rPC, r1
10192    asr     r1, r1, #1
10193    bl      dvmLineNumFromPC
10194    str     r0, [sp, #-4]!
10195    @ dvmGetMethodSourceFile(method)
10196    ldr     r0, [rGLUE, #offGlue_method]
10197    bl      dvmGetMethodSourceFile
10198    str     r0, [sp, #-4]!
10199    @ exception->clazz->descriptor
10200    ldr     r3, [r9, #offObject_clazz]
10201    ldr     r3, [r3, #offClassObject_descriptor]
10202    @
10203    ldr     r2, strExceptionNotCaughtLocally
10204    ldr     r1, strLogTag
10205    mov     r0, #3                      @ LOG_DEBUG
10206    bl      __android_log_print
10207#endif
10208    str     r9, [r10, #offThread_exception] @ restore exception
10209    mov     r0, r9                      @ r0<- exception
10210    mov     r1, r10                     @ r1<- self
10211    bl      dvmReleaseTrackedAlloc      @ release the exception
10212    mov     r1, #0                      @ "want switch" = false
10213    b       common_gotoBail             @ bail out
10214
10215
10216    /*
10217     * Exception handling, calls through "glue code".
10218     */
10219    .if     0
10220.LexceptionOld:
10221    SAVE_PC_FP_TO_GLUE()                @ export state
10222    mov     r0, rGLUE                   @ arg to function
10223    bl      dvmMterp_exceptionThrown
10224    b       common_resumeAfterGlueCall
10225    .endif
10226
10227
10228/*
10229 * After returning from a "glued" function, pull out the updated
10230 * values and start executing at the next instruction.
10231 */
10232common_resumeAfterGlueCall:
10233    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10234    FETCH_INST()                        @ load rINST from rPC
10235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10236    GOTO_OPCODE(ip)                     @ jump to next instruction
10237
10238/*
10239 * Invalid array index.
10240 */
10241common_errArrayIndex:
10242    EXPORT_PC()
10243    ldr     r0, strArrayIndexException
10244    mov     r1, #0
10245    bl      dvmThrowException
10246    b       common_exceptionThrown
10247
10248/*
10249 * Invalid array value.
10250 */
10251common_errArrayStore:
10252    EXPORT_PC()
10253    ldr     r0, strArrayStoreException
10254    mov     r1, #0
10255    bl      dvmThrowException
10256    b       common_exceptionThrown
10257
10258/*
10259 * Integer divide or mod by zero.
10260 */
10261common_errDivideByZero:
10262    EXPORT_PC()
10263    ldr     r0, strArithmeticException
10264    ldr     r1, strDivideByZero
10265    bl      dvmThrowException
10266    b       common_exceptionThrown
10267
10268/*
10269 * Attempt to allocate an array with a negative size.
10270 */
10271common_errNegativeArraySize:
10272    EXPORT_PC()
10273    ldr     r0, strNegativeArraySizeException
10274    mov     r1, #0
10275    bl      dvmThrowException
10276    b       common_exceptionThrown
10277
10278/*
10279 * Invocation of a non-existent method.
10280 */
10281common_errNoSuchMethod:
10282    EXPORT_PC()
10283    ldr     r0, strNoSuchMethodError
10284    mov     r1, #0
10285    bl      dvmThrowException
10286    b       common_exceptionThrown
10287
10288/*
10289 * We encountered a null object when we weren't expecting one.  We
10290 * export the PC, throw a NullPointerException, and goto the exception
10291 * processing code.
10292 */
10293common_errNullObject:
10294    EXPORT_PC()
10295    ldr     r0, strNullPointerException
10296    mov     r1, #0
10297    bl      dvmThrowException
10298    b       common_exceptionThrown
10299
10300/*
10301 * For debugging, cause an immediate fault.  The source address will
10302 * be in lr (use a bl instruction to jump here).
10303 */
10304common_abort:
10305    ldr     pc, .LdeadFood
10306.LdeadFood:
10307    .word   0xdeadf00d
10308
10309/*
10310 * Spit out a "we were here", preserving all registers.  (The attempt
10311 * to save ip won't work, but we need to save an even number of
10312 * registers for EABI 64-bit stack alignment.)
10313 */
10314    .macro  SQUEAK num
10315common_squeak\num:
10316    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10317    ldr     r0, strSqueak
10318    mov     r1, #\num
10319    bl      printf
10320    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10321    bx      lr
10322    .endm
10323
10324    SQUEAK  0
10325    SQUEAK  1
10326    SQUEAK  2
10327    SQUEAK  3
10328    SQUEAK  4
10329    SQUEAK  5
10330
10331/*
10332 * Spit out the number in r0, preserving registers.
10333 */
10334common_printNum:
10335    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10336    mov     r1, r0
10337    ldr     r0, strSqueak
10338    bl      printf
10339    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10340    bx      lr
10341
10342/*
10343 * Print a newline, preserving registers.
10344 */
10345common_printNewline:
10346    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10347    ldr     r0, strNewline
10348    bl      printf
10349    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10350    bx      lr
10351
10352    /*
10353     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10354     */
10355common_printHex:
10356    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10357    mov     r1, r0
10358    ldr     r0, strPrintHex
10359    bl      printf
10360    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10361    bx      lr
10362
10363/*
10364 * Print the 64-bit quantity in r0-r1, preserving registers.
10365 */
10366common_printLong:
10367    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10368    mov     r3, r1
10369    mov     r2, r0
10370    ldr     r0, strPrintLong
10371    bl      printf
10372    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10373    bx      lr
10374
10375/*
10376 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10377 */
10378common_printMethod:
10379    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10380    bl      dvmMterpPrintMethod
10381    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10382    bx      lr
10383
10384/*
10385 * Call a C helper function that dumps regs and possibly some
10386 * additional info.  Requires the C function to be compiled in.
10387 */
10388    .if     0
10389common_dumpRegs:
10390    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10391    bl      dvmMterpDumpArmRegs
10392    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10393    bx      lr
10394    .endif
10395
10396#if 0
10397/*
10398 * Experiment on VFP mode.
10399 *
10400 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10401 *
10402 * Updates the bits specified by "mask", setting them to the values in "val".
10403 */
10404setFPSCR:
10405    and     r0, r0, r1                  @ make sure no stray bits are set
10406    fmrx    r2, fpscr                   @ get VFP reg
10407    mvn     r1, r1                      @ bit-invert mask
10408    and     r2, r2, r1                  @ clear masked bits
10409    orr     r2, r2, r0                  @ set specified bits
10410    fmxr    fpscr, r2                   @ set VFP reg
10411    mov     r0, r2                      @ return new value
10412    bx      lr
10413
10414    .align  2
10415    .global dvmConfigureFP
10416    .type   dvmConfigureFP, %function
10417dvmConfigureFP:
10418    stmfd   sp!, {ip, lr}
10419    /* 0x03000000 sets DN/FZ */
10420    /* 0x00009f00 clears the six exception enable flags */
10421    bl      common_squeak0
10422    mov     r0, #0x03000000             @ r0<- 0x03000000
10423    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10424    bl      setFPSCR
10425    ldmfd   sp!, {ip, pc}
10426#endif
10427
10428
10429/*
10430 * String references, must be close to the code that uses them.
10431 */
10432    .align  2
10433strArithmeticException:
10434    .word   .LstrArithmeticException
10435strArrayIndexException:
10436    .word   .LstrArrayIndexException
10437strArrayStoreException:
10438    .word   .LstrArrayStoreException
10439strDivideByZero:
10440    .word   .LstrDivideByZero
10441strNegativeArraySizeException:
10442    .word   .LstrNegativeArraySizeException
10443strNoSuchMethodError:
10444    .word   .LstrNoSuchMethodError
10445strNullPointerException:
10446    .word   .LstrNullPointerException
10447
10448strLogTag:
10449    .word   .LstrLogTag
10450strExceptionNotCaughtLocally:
10451    .word   .LstrExceptionNotCaughtLocally
10452
10453strNewline:
10454    .word   .LstrNewline
10455strSqueak:
10456    .word   .LstrSqueak
10457strPrintHex:
10458    .word   .LstrPrintHex
10459strPrintLong:
10460    .word   .LstrPrintLong
10461
10462/*
10463 * Zero-terminated ASCII string data.
10464 *
10465 * On ARM we have two choices: do like gcc does, and LDR from a .word
10466 * with the address, or use an ADR pseudo-op to get the address
10467 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10468 * PC-relative addressing mode and hence has a limited range, which
10469 * makes it not work well with mergeable string sections.
10470 */
10471    .section .rodata.str1.4,"aMS",%progbits,1
10472
10473.LstrBadEntryPoint:
10474    .asciz  "Bad entry point %d\n"
10475.LstrArithmeticException:
10476    .asciz  "Ljava/lang/ArithmeticException;"
10477.LstrArrayIndexException:
10478    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10479.LstrArrayStoreException:
10480    .asciz  "Ljava/lang/ArrayStoreException;"
10481.LstrClassCastException:
10482    .asciz  "Ljava/lang/ClassCastException;"
10483.LstrDivideByZero:
10484    .asciz  "divide by zero"
10485.LstrFilledNewArrayNotImpl:
10486    .asciz  "filled-new-array only implemented for objects and 'int'"
10487.LstrInternalError:
10488    .asciz  "Ljava/lang/InternalError;"
10489.LstrInstantiationError:
10490    .asciz  "Ljava/lang/InstantiationError;"
10491.LstrNegativeArraySizeException:
10492    .asciz  "Ljava/lang/NegativeArraySizeException;"
10493.LstrNoSuchMethodError:
10494    .asciz  "Ljava/lang/NoSuchMethodError;"
10495.LstrNullPointerException:
10496    .asciz  "Ljava/lang/NullPointerException;"
10497
10498.LstrLogTag:
10499    .asciz  "mterp"
10500.LstrExceptionNotCaughtLocally:
10501    .asciz  "Exception %s from %s:%d not caught locally\n"
10502
10503.LstrNewline:
10504    .asciz  "\n"
10505.LstrSqueak:
10506    .asciz  "<%d>"
10507.LstrPrintHex:
10508    .asciz  "<0x%x>"
10509.LstrPrintLong:
10510    .asciz  "<%lld>"
10511
10512