InterpAsm-armv7-a.S revision 30f1f463b132c7b6daf2de825c5fa44ce356ca13
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
189#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204
205/* File: armv5te/platform.S */
206/*
207 * ===========================================================================
208 *  CPU-version-specific defines
209 * ===========================================================================
210 */
211
212/*
213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
214 * one-way branch.
215 *
216 * May modify IP.  Does not modify LR.
217 */
218.macro  LDR_PC source
219    ldr     pc, \source
220.endm
221
222/*
223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
224 * Jump to subroutine.
225 *
226 * May modify IP and LR.
227 */
228.macro  LDR_PC_LR source
229    mov     lr, pc
230    ldr     pc, \source
231.endm
232
233/*
234 * Macro for "LDMFD SP!, {...regs...,PC}".
235 *
236 * May modify IP and LR.
237 */
238.macro  LDMFD_PC regs
239    ldmfd   sp!, {\regs,pc}
240.endm
241
242
243/* File: armv5te/entry.S */
244/*
245 * Copyright (C) 2008 The Android Open Source Project
246 *
247 * Licensed under the Apache License, Version 2.0 (the "License");
248 * you may not use this file except in compliance with the License.
249 * You may obtain a copy of the License at
250 *
251 *      http://www.apache.org/licenses/LICENSE-2.0
252 *
253 * Unless required by applicable law or agreed to in writing, software
254 * distributed under the License is distributed on an "AS IS" BASIS,
255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
256 * See the License for the specific language governing permissions and
257 * limitations under the License.
258 */
259/*
260 * Interpreter entry point.
261 */
262
263/*
264 * We don't have formal stack frames, so gdb scans upward in the code
265 * to find the start of the function (a label with the %function type),
266 * and then looks at the next few instructions to figure out what
267 * got pushed onto the stack.  From this it figures out how to restore
268 * the registers, including PC, for the previous stack frame.  If gdb
269 * sees a non-function label, it stops scanning, so either we need to
270 * have nothing but assembler-local labels between the entry point and
271 * the break, or we need to fake it out.
272 *
273 * When this is defined, we add some stuff to make gdb less confused.
274 */
275#define ASSIST_DEBUGGER 1
276
277    .text
278    .align  2
279    .global dvmMterpStdRun
280    .type   dvmMterpStdRun, %function
281
282/*
283 * On entry:
284 *  r0  MterpGlue* glue
285 *
286 * This function returns a boolean "changeInterp" value.  The return comes
287 * via a call to dvmMterpStdBail().
288 */
289dvmMterpStdRun:
290#define MTERP_ENTRY1 \
291    .save {r4-r10,fp,lr}; \
292    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
293#define MTERP_ENTRY2 \
294    .pad    #4; \
295    sub     sp, sp, #4                  @ align 64
296
297    .fnstart
298    MTERP_ENTRY1
299    MTERP_ENTRY2
300
301    /* save stack pointer, add magic word for debuggerd */
302    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
303
304    /* set up "named" registers, figure out entry point */
305    mov     rGLUE, r0                   @ set rGLUE
306    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
307    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
308    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
309    cmp     r1, #kInterpEntryInstr      @ usual case?
310    bne     .Lnot_instr                 @ no, handle it
311
312#if defined(WITH_JIT)
313.Lno_singleStep:
314    /* Entry is always a possible trace start */
315    GET_JIT_PROF_TABLE(r0)
316    FETCH_INST()
317    cmp    r0,#0
318    bne    common_updateProfile
319    GET_INST_OPCODE(ip)
320    GOTO_OPCODE(ip)
321#else
322    /* start executing the instruction at rPC */
323    FETCH_INST()                        @ load rINST from rPC
324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
325    GOTO_OPCODE(ip)                     @ jump to next instruction
326#endif
327
328.Lnot_instr:
329    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
330    beq     common_returnFromMethod
331
332.Lnot_return:
333    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
334    beq     common_exceptionThrown
335
336#if defined(WITH_JIT)
337.Lnot_throw:
338    ldr     r0,[rGLUE, #offGlue_jitResume]
339    ldr     r2,[rGLUE, #offGlue_jitResumePC]
340    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
341    bne     .Lbad_arg
342    cmp     rPC,r2
343    bne     .Lno_singleStep             @ must have branched, don't resume
344    mov     r1, #kInterpEntryInstr
345    strb    r1, [rGLUE, #offGlue_entryPoint]
346    ldr     rINST, .LdvmCompilerTemplate
347    bx      r0                          @ re-enter the translation
348.LdvmCompilerTemplate:
349    .word   dvmCompilerTemplateStart
350#endif
351
352.Lbad_arg:
353    ldr     r0, strBadEntryPoint
354    @ r1 holds value of entryPoint
355    bl      printf
356    bl      dvmAbort
357    .fnend
358
359
360    .global dvmMterpStdBail
361    .type   dvmMterpStdBail, %function
362
363/*
364 * Restore the stack pointer and PC from the save point established on entry.
365 * This is essentially the same as a longjmp, but should be cheaper.  The
366 * last instruction causes us to return to whoever called dvmMterpStdRun.
367 *
368 * We pushed some registers on the stack in dvmMterpStdRun, then saved
369 * SP and LR.  Here we restore SP, restore the registers, and then restore
370 * LR to PC.
371 *
372 * On entry:
373 *  r0  MterpGlue* glue
374 *  r1  bool changeInterp
375 */
376dvmMterpStdBail:
377    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
378    mov     r0, r1                          @ return the changeInterp value
379    add     sp, sp, #4                      @ un-align 64
380    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
381
382
383/*
384 * String references.
385 */
386strBadEntryPoint:
387    .word   .LstrBadEntryPoint
388
389
390
391    .global dvmAsmInstructionStart
392    .type   dvmAsmInstructionStart, %function
393dvmAsmInstructionStart = .L_OP_NOP
394    .text
395
396/* ------------------------------ */
397    .balign 64
398.L_OP_NOP: /* 0x00 */
399/* File: armv5te/OP_NOP.S */
400    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
401    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
402    GOTO_OPCODE(ip)                     @ execute it
403
404#ifdef ASSIST_DEBUGGER
405    /* insert fake function header to help gdb find the stack frame */
406    .type   dalvik_inst, %function
407dalvik_inst:
408    .fnstart
409    MTERP_ENTRY1
410    MTERP_ENTRY2
411    .fnend
412#endif
413
414
415/* ------------------------------ */
416    .balign 64
417.L_OP_MOVE: /* 0x01 */
418/* File: armv6t2/OP_MOVE.S */
419    /* for move, move-object, long-to-int */
420    /* op vA, vB */
421    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
422    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
423    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
424    GET_VREG(r2, r1)                    @ r2<- fp[B]
425    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
426    SET_VREG(r2, r0)                    @ fp[A]<- r2
427    GOTO_OPCODE(ip)                     @ execute next instruction
428
429
430/* ------------------------------ */
431    .balign 64
432.L_OP_MOVE_FROM16: /* 0x02 */
433/* File: armv5te/OP_MOVE_FROM16.S */
434    /* for: move/from16, move-object/from16 */
435    /* op vAA, vBBBB */
436    FETCH(r1, 1)                        @ r1<- BBBB
437    mov     r0, rINST, lsr #8           @ r0<- AA
438    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
439    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
441    SET_VREG(r2, r0)                    @ fp[AA]<- r2
442    GOTO_OPCODE(ip)                     @ jump to next instruction
443
444
445/* ------------------------------ */
446    .balign 64
447.L_OP_MOVE_16: /* 0x03 */
448/* File: armv5te/OP_MOVE_16.S */
449    /* for: move/16, move-object/16 */
450    /* op vAAAA, vBBBB */
451    FETCH(r1, 2)                        @ r1<- BBBB
452    FETCH(r0, 1)                        @ r0<- AAAA
453    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
454    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
456    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
457    GOTO_OPCODE(ip)                     @ jump to next instruction
458
459
460/* ------------------------------ */
461    .balign 64
462.L_OP_MOVE_WIDE: /* 0x04 */
463/* File: armv6t2/OP_MOVE_WIDE.S */
464    /* move-wide vA, vB */
465    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
466    mov     r3, rINST, lsr #12          @ r3<- B
467    ubfx    r2, rINST, #8, #4           @ r2<- A
468    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
469    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
470    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
471    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
472    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
473    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
474    GOTO_OPCODE(ip)                     @ jump to next instruction
475
476
477/* ------------------------------ */
478    .balign 64
479.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
480/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
481    /* move-wide/from16 vAA, vBBBB */
482    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
483    FETCH(r3, 1)                        @ r3<- BBBB
484    mov     r2, rINST, lsr #8           @ r2<- AA
485    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
486    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
487    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
488    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
489    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
490    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
491    GOTO_OPCODE(ip)                     @ jump to next instruction
492
493
494/* ------------------------------ */
495    .balign 64
496.L_OP_MOVE_WIDE_16: /* 0x06 */
497/* File: armv5te/OP_MOVE_WIDE_16.S */
498    /* move-wide/16 vAAAA, vBBBB */
499    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
500    FETCH(r3, 2)                        @ r3<- BBBB
501    FETCH(r2, 1)                        @ r2<- AAAA
502    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
503    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
504    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
505    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
506    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
507    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
508    GOTO_OPCODE(ip)                     @ jump to next instruction
509
510
511/* ------------------------------ */
512    .balign 64
513.L_OP_MOVE_OBJECT: /* 0x07 */
514/* File: armv5te/OP_MOVE_OBJECT.S */
515/* File: armv5te/OP_MOVE.S */
516    /* for move, move-object, long-to-int */
517    /* op vA, vB */
518    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
519    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
520    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
521    GET_VREG(r2, r1)                    @ r2<- fp[B]
522    and     r0, r0, #15
523    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
524    SET_VREG(r2, r0)                    @ fp[A]<- r2
525    GOTO_OPCODE(ip)                     @ execute next instruction
526
527
528
529/* ------------------------------ */
530    .balign 64
531.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
532/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
533/* File: armv5te/OP_MOVE_FROM16.S */
534    /* for: move/from16, move-object/from16 */
535    /* op vAA, vBBBB */
536    FETCH(r1, 1)                        @ r1<- BBBB
537    mov     r0, rINST, lsr #8           @ r0<- AA
538    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
539    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
541    SET_VREG(r2, r0)                    @ fp[AA]<- r2
542    GOTO_OPCODE(ip)                     @ jump to next instruction
543
544
545
546/* ------------------------------ */
547    .balign 64
548.L_OP_MOVE_OBJECT_16: /* 0x09 */
549/* File: armv5te/OP_MOVE_OBJECT_16.S */
550/* File: armv5te/OP_MOVE_16.S */
551    /* for: move/16, move-object/16 */
552    /* op vAAAA, vBBBB */
553    FETCH(r1, 2)                        @ r1<- BBBB
554    FETCH(r0, 1)                        @ r0<- AAAA
555    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
556    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
557    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
558    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
559    GOTO_OPCODE(ip)                     @ jump to next instruction
560
561
562
563/* ------------------------------ */
564    .balign 64
565.L_OP_MOVE_RESULT: /* 0x0a */
566/* File: armv5te/OP_MOVE_RESULT.S */
567    /* for: move-result, move-result-object */
568    /* op vAA */
569    mov     r2, rINST, lsr #8           @ r2<- AA
570    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
571    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
572    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
573    SET_VREG(r0, r2)                    @ fp[AA]<- r0
574    GOTO_OPCODE(ip)                     @ jump to next instruction
575
576
577/* ------------------------------ */
578    .balign 64
579.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
580/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
581    /* move-result-wide vAA */
582    mov     r2, rINST, lsr #8           @ r2<- AA
583    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
584    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
585    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
586    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
587    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
588    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
589    GOTO_OPCODE(ip)                     @ jump to next instruction
590
591
592/* ------------------------------ */
593    .balign 64
594.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
595/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
596/* File: armv5te/OP_MOVE_RESULT.S */
597    /* for: move-result, move-result-object */
598    /* op vAA */
599    mov     r2, rINST, lsr #8           @ r2<- AA
600    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
601    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
602    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
603    SET_VREG(r0, r2)                    @ fp[AA]<- r0
604    GOTO_OPCODE(ip)                     @ jump to next instruction
605
606
607
608/* ------------------------------ */
609    .balign 64
610.L_OP_MOVE_EXCEPTION: /* 0x0d */
611/* File: armv5te/OP_MOVE_EXCEPTION.S */
612    /* move-exception vAA */
613    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
614    mov     r2, rINST, lsr #8           @ r2<- AA
615    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
616    mov     r1, #0                      @ r1<- 0
617    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
618    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
620    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
621    GOTO_OPCODE(ip)                     @ jump to next instruction
622
623
624/* ------------------------------ */
625    .balign 64
626.L_OP_RETURN_VOID: /* 0x0e */
627/* File: armv5te/OP_RETURN_VOID.S */
628    b       common_returnFromMethod
629
630
631/* ------------------------------ */
632    .balign 64
633.L_OP_RETURN: /* 0x0f */
634/* File: armv5te/OP_RETURN.S */
635    /*
636     * Return a 32-bit value.  Copies the return value into the "glue"
637     * structure, then jumps to the return handler.
638     *
639     * for: return, return-object
640     */
641    /* op vAA */
642    mov     r2, rINST, lsr #8           @ r2<- AA
643    GET_VREG(r0, r2)                    @ r0<- vAA
644    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
645    b       common_returnFromMethod
646
647
648/* ------------------------------ */
649    .balign 64
650.L_OP_RETURN_WIDE: /* 0x10 */
651/* File: armv5te/OP_RETURN_WIDE.S */
652    /*
653     * Return a 64-bit value.  Copies the return value into the "glue"
654     * structure, then jumps to the return handler.
655     */
656    /* return-wide vAA */
657    mov     r2, rINST, lsr #8           @ r2<- AA
658    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
659    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
660    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
661    stmia   r3, {r0-r1}                 @ retval<- r0/r1
662    b       common_returnFromMethod
663
664
665/* ------------------------------ */
666    .balign 64
667.L_OP_RETURN_OBJECT: /* 0x11 */
668/* File: armv5te/OP_RETURN_OBJECT.S */
669/* File: armv5te/OP_RETURN.S */
670    /*
671     * Return a 32-bit value.  Copies the return value into the "glue"
672     * structure, then jumps to the return handler.
673     *
674     * for: return, return-object
675     */
676    /* op vAA */
677    mov     r2, rINST, lsr #8           @ r2<- AA
678    GET_VREG(r0, r2)                    @ r0<- vAA
679    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
680    b       common_returnFromMethod
681
682
683
684/* ------------------------------ */
685    .balign 64
686.L_OP_CONST_4: /* 0x12 */
687/* File: armv6t2/OP_CONST_4.S */
688    /* const/4 vA, #+B */
689    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
690    ubfx    r0, rINST, #8, #4           @ r0<- A
691    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
692    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
693    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
694    SET_VREG(r1, r0)                    @ fp[A]<- r1
695    GOTO_OPCODE(ip)                     @ execute next instruction
696
697
698/* ------------------------------ */
699    .balign 64
700.L_OP_CONST_16: /* 0x13 */
701/* File: armv5te/OP_CONST_16.S */
702    /* const/16 vAA, #+BBBB */
703    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
704    mov     r3, rINST, lsr #8           @ r3<- AA
705    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
706    SET_VREG(r0, r3)                    @ vAA<- r0
707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
708    GOTO_OPCODE(ip)                     @ jump to next instruction
709
710
711/* ------------------------------ */
712    .balign 64
713.L_OP_CONST: /* 0x14 */
714/* File: armv5te/OP_CONST.S */
715    /* const vAA, #+BBBBbbbb */
716    mov     r3, rINST, lsr #8           @ r3<- AA
717    FETCH(r0, 1)                        @ r0<- bbbb (low)
718    FETCH(r1, 2)                        @ r1<- BBBB (high)
719    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
720    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
722    SET_VREG(r0, r3)                    @ vAA<- r0
723    GOTO_OPCODE(ip)                     @ jump to next instruction
724
725
726/* ------------------------------ */
727    .balign 64
728.L_OP_CONST_HIGH16: /* 0x15 */
729/* File: armv5te/OP_CONST_HIGH16.S */
730    /* const/high16 vAA, #+BBBB0000 */
731    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
732    mov     r3, rINST, lsr #8           @ r3<- AA
733    mov     r0, r0, lsl #16             @ r0<- BBBB0000
734    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
735    SET_VREG(r0, r3)                    @ vAA<- r0
736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
737    GOTO_OPCODE(ip)                     @ jump to next instruction
738
739
740/* ------------------------------ */
741    .balign 64
742.L_OP_CONST_WIDE_16: /* 0x16 */
743/* File: armv5te/OP_CONST_WIDE_16.S */
744    /* const-wide/16 vAA, #+BBBB */
745    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
746    mov     r3, rINST, lsr #8           @ r3<- AA
747    mov     r1, r0, asr #31             @ r1<- ssssssss
748    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
749    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
751    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
752    GOTO_OPCODE(ip)                     @ jump to next instruction
753
754
755/* ------------------------------ */
756    .balign 64
757.L_OP_CONST_WIDE_32: /* 0x17 */
758/* File: armv5te/OP_CONST_WIDE_32.S */
759    /* const-wide/32 vAA, #+BBBBbbbb */
760    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
761    mov     r3, rINST, lsr #8           @ r3<- AA
762    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
763    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
764    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
765    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
766    mov     r1, r0, asr #31             @ r1<- ssssssss
767    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
768    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
769    GOTO_OPCODE(ip)                     @ jump to next instruction
770
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/* ------------------------------ */
792    .balign 64
793.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
794/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
795    /* const-wide/high16 vAA, #+BBBB000000000000 */
796    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
797    mov     r3, rINST, lsr #8           @ r3<- AA
798    mov     r0, #0                      @ r0<- 00000000
799    mov     r1, r1, lsl #16             @ r1<- BBBB0000
800    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
801    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
803    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
804    GOTO_OPCODE(ip)                     @ jump to next instruction
805
806
807/* ------------------------------ */
808    .balign 64
809.L_OP_CONST_STRING: /* 0x1a */
810/* File: armv5te/OP_CONST_STRING.S */
811    /* const/string vAA, String@BBBB */
812    FETCH(r1, 1)                        @ r1<- BBBB
813    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
814    mov     r9, rINST, lsr #8           @ r9<- AA
815    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
816    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
817    cmp     r0, #0                      @ not yet resolved?
818    beq     .LOP_CONST_STRING_resolve
819    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
820    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
821    SET_VREG(r0, r9)                    @ vAA<- r0
822    GOTO_OPCODE(ip)                     @ jump to next instruction
823
824/* ------------------------------ */
825    .balign 64
826.L_OP_CONST_STRING_JUMBO: /* 0x1b */
827/* File: armv5te/OP_CONST_STRING_JUMBO.S */
828    /* const/string vAA, String@BBBBBBBB */
829    FETCH(r0, 1)                        @ r0<- bbbb (low)
830    FETCH(r1, 2)                        @ r1<- BBBB (high)
831    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
832    mov     r9, rINST, lsr #8           @ r9<- AA
833    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
834    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
835    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
836    cmp     r0, #0
837    beq     .LOP_CONST_STRING_JUMBO_resolve
838    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
840    SET_VREG(r0, r9)                    @ vAA<- r0
841    GOTO_OPCODE(ip)                     @ jump to next instruction
842
843/* ------------------------------ */
844    .balign 64
845.L_OP_CONST_CLASS: /* 0x1c */
846/* File: armv5te/OP_CONST_CLASS.S */
847    /* const/class vAA, Class@BBBB */
848    FETCH(r1, 1)                        @ r1<- BBBB
849    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
850    mov     r9, rINST, lsr #8           @ r9<- AA
851    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
852    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
853    cmp     r0, #0                      @ not yet resolved?
854    beq     .LOP_CONST_CLASS_resolve
855    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
857    SET_VREG(r0, r9)                    @ vAA<- r0
858    GOTO_OPCODE(ip)                     @ jump to next instruction
859
860/* ------------------------------ */
861    .balign 64
862.L_OP_MONITOR_ENTER: /* 0x1d */
863/* File: armv5te/OP_MONITOR_ENTER.S */
864    /*
865     * Synchronize on an object.
866     */
867    /* monitor-enter vAA */
868    mov     r2, rINST, lsr #8           @ r2<- AA
869    GET_VREG(r1, r2)                    @ r1<- vAA (object)
870    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
871    cmp     r1, #0                      @ null object?
872    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
873    beq     common_errNullObject        @ null object, throw an exception
874    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
875    bl      dvmLockObject               @ call(self, obj)
876#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
877    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
878    ldr     r1, [r0, #offThread_exception] @ check for exception
879    cmp     r1, #0
880    bne     common_exceptionThrown      @ exception raised, bail out
881#endif
882    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
883    GOTO_OPCODE(ip)                     @ jump to next instruction
884
885
886/* ------------------------------ */
887    .balign 64
888.L_OP_MONITOR_EXIT: /* 0x1e */
889/* File: armv5te/OP_MONITOR_EXIT.S */
890    /*
891     * Unlock an object.
892     *
893     * Exceptions that occur when unlocking a monitor need to appear as
894     * if they happened at the following instruction.  See the Dalvik
895     * instruction spec.
896     */
897    /* monitor-exit vAA */
898    mov     r2, rINST, lsr #8           @ r2<- AA
899    EXPORT_PC()                         @ before fetch: export the PC
900    GET_VREG(r1, r2)                    @ r1<- vAA (object)
901    cmp     r1, #0                      @ null object?
902    beq     common_errNullObject        @ yes
903    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
904    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
905    cmp     r0, #0                      @ failed?
906    beq     common_exceptionThrown      @ yes, exception is pending
907    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
909    GOTO_OPCODE(ip)                     @ jump to next instruction
910
911
912/* ------------------------------ */
913    .balign 64
914.L_OP_CHECK_CAST: /* 0x1f */
915/* File: armv5te/OP_CHECK_CAST.S */
916    /*
917     * Check to see if a cast from one class to another is allowed.
918     */
919    /* check-cast vAA, class@BBBB */
920    mov     r3, rINST, lsr #8           @ r3<- AA
921    FETCH(r2, 1)                        @ r2<- BBBB
922    GET_VREG(r9, r3)                    @ r9<- object
923    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
924    cmp     r9, #0                      @ is object null?
925    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
926    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
927    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
928    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
929    cmp     r1, #0                      @ have we resolved this before?
930    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
931.LOP_CHECK_CAST_resolved:
932    cmp     r0, r1                      @ same class (trivial success)?
933    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
934.LOP_CHECK_CAST_okay:
935    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
936    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
937    GOTO_OPCODE(ip)                     @ jump to next instruction
938
939/* ------------------------------ */
940    .balign 64
941.L_OP_INSTANCE_OF: /* 0x20 */
942/* File: armv5te/OP_INSTANCE_OF.S */
943    /*
944     * Check to see if an object reference is an instance of a class.
945     *
946     * Most common situation is a non-null object, being compared against
947     * an already-resolved class.
948     */
949    /* instance-of vA, vB, class@CCCC */
950    mov     r3, rINST, lsr #12          @ r3<- B
951    mov     r9, rINST, lsr #8           @ r9<- A+
952    GET_VREG(r0, r3)                    @ r0<- vB (object)
953    and     r9, r9, #15                 @ r9<- A
954    cmp     r0, #0                      @ is object null?
955    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
956    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
957    FETCH(r3, 1)                        @ r3<- CCCC
958    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
959    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
960    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
961    cmp     r1, #0                      @ have we resolved this before?
962    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
963.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
964    cmp     r0, r1                      @ same class (trivial success)?
965    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
966    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
967
968/* ------------------------------ */
969    .balign 64
970.L_OP_ARRAY_LENGTH: /* 0x21 */
971/* File: armv6t2/OP_ARRAY_LENGTH.S */
972    /*
973     * Return the length of an array.
974     */
975    mov     r1, rINST, lsr #12          @ r1<- B
976    ubfx    r2, rINST, #8, #4           @ r2<- A
977    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
978    cmp     r0, #0                      @ is object null?
979    beq     common_errNullObject        @ yup, fail
980    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
981    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
982    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
983    SET_VREG(r3, r2)                    @ vB<- length
984    GOTO_OPCODE(ip)                     @ jump to next instruction
985
986
987/* ------------------------------ */
988    .balign 64
989.L_OP_NEW_INSTANCE: /* 0x22 */
990/* File: armv5te/OP_NEW_INSTANCE.S */
991    /*
992     * Create a new instance of a class.
993     */
994    /* new-instance vAA, class@BBBB */
995    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
996    FETCH(r1, 1)                        @ r1<- BBBB
997    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
998    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
999    EXPORT_PC()                         @ req'd for init, resolve, alloc
1000    cmp     r0, #0                      @ already resolved?
1001    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1002.LOP_NEW_INSTANCE_resolved:   @ r0=class
1003    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1004    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1005    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1006.LOP_NEW_INSTANCE_initialized: @ r0=class
1007    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1008    bl      dvmAllocObject              @ r0<- new object
1009    b       .LOP_NEW_INSTANCE_finish          @ continue
1010
1011/* ------------------------------ */
1012    .balign 64
1013.L_OP_NEW_ARRAY: /* 0x23 */
1014/* File: armv5te/OP_NEW_ARRAY.S */
1015    /*
1016     * Allocate an array of objects, specified with the array class
1017     * and a count.
1018     *
1019     * The verifier guarantees that this is an array class, so we don't
1020     * check for it here.
1021     */
1022    /* new-array vA, vB, class@CCCC */
1023    mov     r0, rINST, lsr #12          @ r0<- B
1024    FETCH(r2, 1)                        @ r2<- CCCC
1025    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1026    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1027    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1028    cmp     r1, #0                      @ check length
1029    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1030    bmi     common_errNegativeArraySize @ negative length, bail
1031    cmp     r0, #0                      @ already resolved?
1032    EXPORT_PC()                         @ req'd for resolve, alloc
1033    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1034    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1035
1036/* ------------------------------ */
1037    .balign 64
1038.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1039/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1040    /*
1041     * Create a new array with elements filled from registers.
1042     *
1043     * for: filled-new-array, filled-new-array/range
1044     */
1045    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1046    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1047    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1048    FETCH(r1, 1)                        @ r1<- BBBB
1049    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1050    EXPORT_PC()                         @ need for resolve and alloc
1051    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1052    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1053    cmp     r0, #0                      @ already resolved?
1054    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10558:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1056    mov     r2, #0                      @ r2<- false
1057    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1058    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1059    cmp     r0, #0                      @ got null?
1060    beq     common_exceptionThrown      @ yes, handle exception
1061    b       .LOP_FILLED_NEW_ARRAY_continue
1062
1063/* ------------------------------ */
1064    .balign 64
1065.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1066/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1067/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1068    /*
1069     * Create a new array with elements filled from registers.
1070     *
1071     * for: filled-new-array, filled-new-array/range
1072     */
1073    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1074    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1075    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1076    FETCH(r1, 1)                        @ r1<- BBBB
1077    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1078    EXPORT_PC()                         @ need for resolve and alloc
1079    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1080    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1081    cmp     r0, #0                      @ already resolved?
1082    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10838:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1084    mov     r2, #0                      @ r2<- false
1085    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1086    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1087    cmp     r0, #0                      @ got null?
1088    beq     common_exceptionThrown      @ yes, handle exception
1089    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1090
1091
1092/* ------------------------------ */
1093    .balign 64
1094.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1095/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1096    /* fill-array-data vAA, +BBBBBBBB */
1097    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1098    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1099    mov     r3, rINST, lsr #8           @ r3<- AA
1100    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1101    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1102    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1103    EXPORT_PC();
1104    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1105    cmp     r0, #0                      @ 0 means an exception is thrown
1106    beq     common_exceptionThrown      @ has exception
1107    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1108    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1109    GOTO_OPCODE(ip)                     @ jump to next instruction
1110
1111/* ------------------------------ */
1112    .balign 64
1113.L_OP_THROW: /* 0x27 */
1114/* File: armv5te/OP_THROW.S */
1115    /*
1116     * Throw an exception object in the current thread.
1117     */
1118    /* throw vAA */
1119    mov     r2, rINST, lsr #8           @ r2<- AA
1120    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1121    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1122    cmp     r1, #0                      @ null object?
1123    beq     common_errNullObject        @ yes, throw an NPE instead
1124    @ bypass dvmSetException, just store it
1125    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1126    b       common_exceptionThrown
1127
1128
1129/* ------------------------------ */
1130    .balign 64
1131.L_OP_GOTO: /* 0x28 */
1132/* File: armv5te/OP_GOTO.S */
1133    /*
1134     * Unconditional branch, 8-bit offset.
1135     *
1136     * The branch distance is a signed code-unit offset, which we need to
1137     * double to get a byte offset.
1138     */
1139    /* goto +AA */
1140    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1141    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1142    mov     r9, r9, lsl #1              @ r9<- byte offset
1143    bmi     common_backwardBranch       @ backward branch, do periodic checks
1144#if defined(WITH_JIT)
1145    GET_JIT_PROF_TABLE(r0)
1146    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1147    cmp     r0,#0
1148    bne     common_updateProfile
1149    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1150    GOTO_OPCODE(ip)                     @ jump to next instruction
1151#else
1152    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1153    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1154    GOTO_OPCODE(ip)                     @ jump to next instruction
1155#endif
1156
1157/* ------------------------------ */
1158    .balign 64
1159.L_OP_GOTO_16: /* 0x29 */
1160/* File: armv5te/OP_GOTO_16.S */
1161    /*
1162     * Unconditional branch, 16-bit offset.
1163     *
1164     * The branch distance is a signed code-unit offset, which we need to
1165     * double to get a byte offset.
1166     */
1167    /* goto/16 +AAAA */
1168    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1169    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1170    bmi     common_backwardBranch       @ backward branch, do periodic checks
1171#if defined(WITH_JIT)
1172    GET_JIT_PROF_TABLE(r0)
1173    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1174    cmp     r0,#0
1175    bne     common_updateProfile
1176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1177    GOTO_OPCODE(ip)                     @ jump to next instruction
1178#else
1179    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1181    GOTO_OPCODE(ip)                     @ jump to next instruction
1182#endif
1183
1184
1185/* ------------------------------ */
1186    .balign 64
1187.L_OP_GOTO_32: /* 0x2a */
1188/* File: armv5te/OP_GOTO_32.S */
1189    /*
1190     * Unconditional branch, 32-bit offset.
1191     *
1192     * The branch distance is a signed code-unit offset, which we need to
1193     * double to get a byte offset.
1194     *
1195     * Unlike most opcodes, this one is allowed to branch to itself, so
1196     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1197     * instruction doesn't affect the V flag, so we need to clear it
1198     * explicitly.
1199     */
1200    /* goto/32 +AAAAAAAA */
1201    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1202    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1203    cmp     ip, ip                      @ (clear V flag during stall)
1204    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1205    mov     r9, r0, asl #1              @ r9<- byte offset
1206    ble     common_backwardBranch       @ backward branch, do periodic checks
1207#if defined(WITH_JIT)
1208    GET_JIT_PROF_TABLE(r0)
1209    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1210    cmp     r0,#0
1211    bne     common_updateProfile
1212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1213    GOTO_OPCODE(ip)                     @ jump to next instruction
1214#else
1215    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1217    GOTO_OPCODE(ip)                     @ jump to next instruction
1218#endif
1219
1220/* ------------------------------ */
1221    .balign 64
1222.L_OP_PACKED_SWITCH: /* 0x2b */
1223/* File: armv5te/OP_PACKED_SWITCH.S */
1224    /*
1225     * Handle a packed-switch or sparse-switch instruction.  In both cases
1226     * we decode it and hand it off to a helper function.
1227     *
1228     * We don't really expect backward branches in a switch statement, but
1229     * they're perfectly legal, so we check for them here.
1230     *
1231     * for: packed-switch, sparse-switch
1232     */
1233    /* op vAA, +BBBB */
1234    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1235    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1236    mov     r3, rINST, lsr #8           @ r3<- AA
1237    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1238    GET_VREG(r1, r3)                    @ r1<- vAA
1239    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1240    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1241    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1242    bmi     common_backwardBranch       @ backward branch, do periodic checks
1243    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1244#if defined(WITH_JIT)
1245    GET_JIT_PROF_TABLE(r0)
1246    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1247    cmp     r0,#0
1248    bne     common_updateProfile
1249    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1250    GOTO_OPCODE(ip)                     @ jump to next instruction
1251#else
1252    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1254    GOTO_OPCODE(ip)                     @ jump to next instruction
1255#endif
1256
1257
1258/* ------------------------------ */
1259    .balign 64
1260.L_OP_SPARSE_SWITCH: /* 0x2c */
1261/* File: armv5te/OP_SPARSE_SWITCH.S */
1262/* File: armv5te/OP_PACKED_SWITCH.S */
1263    /*
1264     * Handle a packed-switch or sparse-switch instruction.  In both cases
1265     * we decode it and hand it off to a helper function.
1266     *
1267     * We don't really expect backward branches in a switch statement, but
1268     * they're perfectly legal, so we check for them here.
1269     *
1270     * for: packed-switch, sparse-switch
1271     */
1272    /* op vAA, +BBBB */
1273    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1274    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1275    mov     r3, rINST, lsr #8           @ r3<- AA
1276    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1277    GET_VREG(r1, r3)                    @ r1<- vAA
1278    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1279    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1280    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1281    bmi     common_backwardBranch       @ backward branch, do periodic checks
1282    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1283#if defined(WITH_JIT)
1284    GET_JIT_PROF_TABLE(r0)
1285    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1286    cmp     r0,#0
1287    bne     common_updateProfile
1288    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1289    GOTO_OPCODE(ip)                     @ jump to next instruction
1290#else
1291    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1292    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1293    GOTO_OPCODE(ip)                     @ jump to next instruction
1294#endif
1295
1296
1297
1298/* ------------------------------ */
1299    .balign 64
1300.L_OP_CMPL_FLOAT: /* 0x2d */
1301/* File: arm-vfp/OP_CMPL_FLOAT.S */
1302    /*
1303     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1304     * destination register based on the results of the comparison.
1305     *
1306     * int compare(x, y) {
1307     *     if (x == y) {
1308     *         return 0;
1309     *     } else if (x > y) {
1310     *         return 1;
1311     *     } else if (x < y) {
1312     *         return -1;
1313     *     } else {
1314     *         return -1;
1315     *     }
1316     * }
1317     */
1318    /* op vAA, vBB, vCC */
1319    FETCH(r0, 1)                        @ r0<- CCBB
1320    mov     r9, rINST, lsr #8           @ r9<- AA
1321    and     r2, r0, #255                @ r2<- BB
1322    mov     r3, r0, lsr #8              @ r3<- CC
1323    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1324    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1325    flds    s0, [r2]                    @ s0<- vBB
1326    flds    s1, [r3]                    @ s1<- vCC
1327    fcmpes  s0, s1                      @ compare (vBB, vCC)
1328    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1329    mvn     r0, #0                      @ r0<- -1 (default)
1330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1331    fmstat                              @ export status flags
1332    movgt   r0, #1                      @ (greater than) r1<- 1
1333    moveq   r0, #0                      @ (equal) r1<- 0
1334    b       .LOP_CMPL_FLOAT_finish          @ argh
1335
1336
1337/* ------------------------------ */
1338    .balign 64
1339.L_OP_CMPG_FLOAT: /* 0x2e */
1340/* File: arm-vfp/OP_CMPG_FLOAT.S */
1341    /*
1342     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1343     * destination register based on the results of the comparison.
1344     *
1345     * int compare(x, y) {
1346     *     if (x == y) {
1347     *         return 0;
1348     *     } else if (x < y) {
1349     *         return -1;
1350     *     } else if (x > y) {
1351     *         return 1;
1352     *     } else {
1353     *         return 1;
1354     *     }
1355     * }
1356     */
1357    /* op vAA, vBB, vCC */
1358    FETCH(r0, 1)                        @ r0<- CCBB
1359    mov     r9, rINST, lsr #8           @ r9<- AA
1360    and     r2, r0, #255                @ r2<- BB
1361    mov     r3, r0, lsr #8              @ r3<- CC
1362    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1363    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1364    flds    s0, [r2]                    @ s0<- vBB
1365    flds    s1, [r3]                    @ s1<- vCC
1366    fcmpes  s0, s1                      @ compare (vBB, vCC)
1367    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1368    mov     r0, #1                      @ r0<- 1 (default)
1369    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1370    fmstat                              @ export status flags
1371    mvnmi   r0, #0                      @ (less than) r1<- -1
1372    moveq   r0, #0                      @ (equal) r1<- 0
1373    b       .LOP_CMPG_FLOAT_finish          @ argh
1374
1375
1376/* ------------------------------ */
1377    .balign 64
1378.L_OP_CMPL_DOUBLE: /* 0x2f */
1379/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1380    /*
1381     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1382     * destination register based on the results of the comparison.
1383     *
1384     * int compare(x, y) {
1385     *     if (x == y) {
1386     *         return 0;
1387     *     } else if (x > y) {
1388     *         return 1;
1389     *     } else if (x < y) {
1390     *         return -1;
1391     *     } else {
1392     *         return -1;
1393     *     }
1394     * }
1395     */
1396    /* op vAA, vBB, vCC */
1397    FETCH(r0, 1)                        @ r0<- CCBB
1398    mov     r9, rINST, lsr #8           @ r9<- AA
1399    and     r2, r0, #255                @ r2<- BB
1400    mov     r3, r0, lsr #8              @ r3<- CC
1401    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1402    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1403    fldd    d0, [r2]                    @ d0<- vBB
1404    fldd    d1, [r3]                    @ d1<- vCC
1405    fcmped  d0, d1                      @ compare (vBB, vCC)
1406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1407    mvn     r0, #0                      @ r0<- -1 (default)
1408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1409    fmstat                              @ export status flags
1410    movgt   r0, #1                      @ (greater than) r1<- 1
1411    moveq   r0, #0                      @ (equal) r1<- 0
1412    b       .LOP_CMPL_DOUBLE_finish          @ argh
1413
1414
1415/* ------------------------------ */
1416    .balign 64
1417.L_OP_CMPG_DOUBLE: /* 0x30 */
1418/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1419    /*
1420     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1421     * destination register based on the results of the comparison.
1422     *
1423     * int compare(x, y) {
1424     *     if (x == y) {
1425     *         return 0;
1426     *     } else if (x < y) {
1427     *         return -1;
1428     *     } else if (x > y) {
1429     *         return 1;
1430     *     } else {
1431     *         return 1;
1432     *     }
1433     * }
1434     */
1435    /* op vAA, vBB, vCC */
1436    FETCH(r0, 1)                        @ r0<- CCBB
1437    mov     r9, rINST, lsr #8           @ r9<- AA
1438    and     r2, r0, #255                @ r2<- BB
1439    mov     r3, r0, lsr #8              @ r3<- CC
1440    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1441    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1442    fldd    d0, [r2]                    @ d0<- vBB
1443    fldd    d1, [r3]                    @ d1<- vCC
1444    fcmped  d0, d1                      @ compare (vBB, vCC)
1445    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1446    mov     r0, #1                      @ r0<- 1 (default)
1447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1448    fmstat                              @ export status flags
1449    mvnmi   r0, #0                      @ (less than) r1<- -1
1450    moveq   r0, #0                      @ (equal) r1<- 0
1451    b       .LOP_CMPG_DOUBLE_finish          @ argh
1452
1453
1454/* ------------------------------ */
1455    .balign 64
1456.L_OP_CMP_LONG: /* 0x31 */
1457/* File: armv5te/OP_CMP_LONG.S */
1458    /*
1459     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1460     * register based on the results of the comparison.
1461     *
1462     * We load the full values with LDM, but in practice many values could
1463     * be resolved by only looking at the high word.  This could be made
1464     * faster or slower by splitting the LDM into a pair of LDRs.
1465     *
1466     * If we just wanted to set condition flags, we could do this:
1467     *  subs    ip, r0, r2
1468     *  sbcs    ip, r1, r3
1469     *  subeqs  ip, r0, r2
1470     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1471     * integer value, which we can do with 2 conditional mov/mvn instructions
1472     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1473     * us a constant 5-cycle path plus a branch at the end to the
1474     * instruction epilogue code.  The multi-compare approach below needs
1475     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1476     * in the worst case (the 64-bit values are equal).
1477     */
1478    /* cmp-long vAA, vBB, vCC */
1479    FETCH(r0, 1)                        @ r0<- CCBB
1480    mov     r9, rINST, lsr #8           @ r9<- AA
1481    and     r2, r0, #255                @ r2<- BB
1482    mov     r3, r0, lsr #8              @ r3<- CC
1483    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1484    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1485    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1486    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1487    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1488    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1489    bgt     .LOP_CMP_LONG_greater
1490    subs    r1, r0, r2                  @ r1<- r0 - r2
1491    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1492    bne     .LOP_CMP_LONG_less
1493    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1494
1495/* ------------------------------ */
1496    .balign 64
1497.L_OP_IF_EQ: /* 0x32 */
1498/* File: armv6t2/OP_IF_EQ.S */
1499/* File: armv6t2/bincmp.S */
1500    /*
1501     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1502     * fragment that specifies the *reverse* comparison to perform, e.g.
1503     * for "if-le" you would use "gt".
1504     *
1505     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1506     */
1507    /* if-cmp vA, vB, +CCCC */
1508    mov     r1, rINST, lsr #12          @ r1<- B
1509    ubfx    r0, rINST, #8, #4           @ r0<- A
1510    GET_VREG(r3, r1)                    @ r3<- vB
1511    GET_VREG(r2, r0)                    @ r2<- vA
1512    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1513    cmp     r2, r3                      @ compare (vA, vB)
1514    bne  1f                      @ branch to 1 if comparison failed
1515    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1516    movs    r9, r9, asl #1              @ convert to bytes, check sign
1517    bmi     common_backwardBranch       @ yes, do periodic checks
15181:
1519#if defined(WITH_JIT)
1520    GET_JIT_PROF_TABLE(r0)
1521    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1522    b        common_testUpdateProfile
1523#else
1524    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1525    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1526    GOTO_OPCODE(ip)                     @ jump to next instruction
1527#endif
1528
1529
1530
1531/* ------------------------------ */
1532    .balign 64
1533.L_OP_IF_NE: /* 0x33 */
1534/* File: armv6t2/OP_IF_NE.S */
1535/* File: armv6t2/bincmp.S */
1536    /*
1537     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1538     * fragment that specifies the *reverse* comparison to perform, e.g.
1539     * for "if-le" you would use "gt".
1540     *
1541     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1542     */
1543    /* if-cmp vA, vB, +CCCC */
1544    mov     r1, rINST, lsr #12          @ r1<- B
1545    ubfx    r0, rINST, #8, #4           @ r0<- A
1546    GET_VREG(r3, r1)                    @ r3<- vB
1547    GET_VREG(r2, r0)                    @ r2<- vA
1548    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1549    cmp     r2, r3                      @ compare (vA, vB)
1550    beq  1f                      @ branch to 1 if comparison failed
1551    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1552    movs    r9, r9, asl #1              @ convert to bytes, check sign
1553    bmi     common_backwardBranch       @ yes, do periodic checks
15541:
1555#if defined(WITH_JIT)
1556    GET_JIT_PROF_TABLE(r0)
1557    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1558    b        common_testUpdateProfile
1559#else
1560    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1561    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1562    GOTO_OPCODE(ip)                     @ jump to next instruction
1563#endif
1564
1565
1566
1567/* ------------------------------ */
1568    .balign 64
1569.L_OP_IF_LT: /* 0x34 */
1570/* File: armv6t2/OP_IF_LT.S */
1571/* File: armv6t2/bincmp.S */
1572    /*
1573     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1574     * fragment that specifies the *reverse* comparison to perform, e.g.
1575     * for "if-le" you would use "gt".
1576     *
1577     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1578     */
1579    /* if-cmp vA, vB, +CCCC */
1580    mov     r1, rINST, lsr #12          @ r1<- B
1581    ubfx    r0, rINST, #8, #4           @ r0<- A
1582    GET_VREG(r3, r1)                    @ r3<- vB
1583    GET_VREG(r2, r0)                    @ r2<- vA
1584    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1585    cmp     r2, r3                      @ compare (vA, vB)
1586    bge  1f                      @ branch to 1 if comparison failed
1587    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1588    movs    r9, r9, asl #1              @ convert to bytes, check sign
1589    bmi     common_backwardBranch       @ yes, do periodic checks
15901:
1591#if defined(WITH_JIT)
1592    GET_JIT_PROF_TABLE(r0)
1593    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1594    b        common_testUpdateProfile
1595#else
1596    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1597    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1598    GOTO_OPCODE(ip)                     @ jump to next instruction
1599#endif
1600
1601
1602
1603/* ------------------------------ */
1604    .balign 64
1605.L_OP_IF_GE: /* 0x35 */
1606/* File: armv6t2/OP_IF_GE.S */
1607/* File: armv6t2/bincmp.S */
1608    /*
1609     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1610     * fragment that specifies the *reverse* comparison to perform, e.g.
1611     * for "if-le" you would use "gt".
1612     *
1613     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1614     */
1615    /* if-cmp vA, vB, +CCCC */
1616    mov     r1, rINST, lsr #12          @ r1<- B
1617    ubfx    r0, rINST, #8, #4           @ r0<- A
1618    GET_VREG(r3, r1)                    @ r3<- vB
1619    GET_VREG(r2, r0)                    @ r2<- vA
1620    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1621    cmp     r2, r3                      @ compare (vA, vB)
1622    blt  1f                      @ branch to 1 if comparison failed
1623    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1624    movs    r9, r9, asl #1              @ convert to bytes, check sign
1625    bmi     common_backwardBranch       @ yes, do periodic checks
16261:
1627#if defined(WITH_JIT)
1628    GET_JIT_PROF_TABLE(r0)
1629    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1630    b        common_testUpdateProfile
1631#else
1632    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1633    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1634    GOTO_OPCODE(ip)                     @ jump to next instruction
1635#endif
1636
1637
1638
1639/* ------------------------------ */
1640    .balign 64
1641.L_OP_IF_GT: /* 0x36 */
1642/* File: armv6t2/OP_IF_GT.S */
1643/* File: armv6t2/bincmp.S */
1644    /*
1645     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1646     * fragment that specifies the *reverse* comparison to perform, e.g.
1647     * for "if-le" you would use "gt".
1648     *
1649     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1650     */
1651    /* if-cmp vA, vB, +CCCC */
1652    mov     r1, rINST, lsr #12          @ r1<- B
1653    ubfx    r0, rINST, #8, #4           @ r0<- A
1654    GET_VREG(r3, r1)                    @ r3<- vB
1655    GET_VREG(r2, r0)                    @ r2<- vA
1656    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1657    cmp     r2, r3                      @ compare (vA, vB)
1658    ble  1f                      @ branch to 1 if comparison failed
1659    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1660    movs    r9, r9, asl #1              @ convert to bytes, check sign
1661    bmi     common_backwardBranch       @ yes, do periodic checks
16621:
1663#if defined(WITH_JIT)
1664    GET_JIT_PROF_TABLE(r0)
1665    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1666    b        common_testUpdateProfile
1667#else
1668    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1669    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1670    GOTO_OPCODE(ip)                     @ jump to next instruction
1671#endif
1672
1673
1674
1675/* ------------------------------ */
1676    .balign 64
1677.L_OP_IF_LE: /* 0x37 */
1678/* File: armv6t2/OP_IF_LE.S */
1679/* File: armv6t2/bincmp.S */
1680    /*
1681     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1682     * fragment that specifies the *reverse* comparison to perform, e.g.
1683     * for "if-le" you would use "gt".
1684     *
1685     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1686     */
1687    /* if-cmp vA, vB, +CCCC */
1688    mov     r1, rINST, lsr #12          @ r1<- B
1689    ubfx    r0, rINST, #8, #4           @ r0<- A
1690    GET_VREG(r3, r1)                    @ r3<- vB
1691    GET_VREG(r2, r0)                    @ r2<- vA
1692    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1693    cmp     r2, r3                      @ compare (vA, vB)
1694    bgt  1f                      @ branch to 1 if comparison failed
1695    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1696    movs    r9, r9, asl #1              @ convert to bytes, check sign
1697    bmi     common_backwardBranch       @ yes, do periodic checks
16981:
1699#if defined(WITH_JIT)
1700    GET_JIT_PROF_TABLE(r0)
1701    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1702    b        common_testUpdateProfile
1703#else
1704    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1706    GOTO_OPCODE(ip)                     @ jump to next instruction
1707#endif
1708
1709
1710
1711/* ------------------------------ */
1712    .balign 64
1713.L_OP_IF_EQZ: /* 0x38 */
1714/* File: armv5te/OP_IF_EQZ.S */
1715/* File: armv5te/zcmp.S */
1716    /*
1717     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1718     * fragment that specifies the *reverse* comparison to perform, e.g.
1719     * for "if-le" you would use "gt".
1720     *
1721     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1722     */
1723    /* if-cmp vAA, +BBBB */
1724    mov     r0, rINST, lsr #8           @ r0<- AA
1725    GET_VREG(r2, r0)                    @ r2<- vAA
1726    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1727    cmp     r2, #0                      @ compare (vA, 0)
1728    bne  1f                      @ branch to 1 if comparison failed
1729    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1730    movs    r9, r9, asl #1              @ convert to bytes, check sign
1731    bmi     common_backwardBranch       @ backward branch, do periodic checks
17321:
1733#if defined(WITH_JIT)
1734    GET_JIT_PROF_TABLE(r0)
1735    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1736    cmp     r0,#0
1737    bne     common_updateProfile
1738    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1739    GOTO_OPCODE(ip)                     @ jump to next instruction
1740#else
1741    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1743    GOTO_OPCODE(ip)                     @ jump to next instruction
1744#endif
1745
1746
1747
1748/* ------------------------------ */
1749    .balign 64
1750.L_OP_IF_NEZ: /* 0x39 */
1751/* File: armv5te/OP_IF_NEZ.S */
1752/* File: armv5te/zcmp.S */
1753    /*
1754     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1755     * fragment that specifies the *reverse* comparison to perform, e.g.
1756     * for "if-le" you would use "gt".
1757     *
1758     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1759     */
1760    /* if-cmp vAA, +BBBB */
1761    mov     r0, rINST, lsr #8           @ r0<- AA
1762    GET_VREG(r2, r0)                    @ r2<- vAA
1763    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1764    cmp     r2, #0                      @ compare (vA, 0)
1765    beq  1f                      @ branch to 1 if comparison failed
1766    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1767    movs    r9, r9, asl #1              @ convert to bytes, check sign
1768    bmi     common_backwardBranch       @ backward branch, do periodic checks
17691:
1770#if defined(WITH_JIT)
1771    GET_JIT_PROF_TABLE(r0)
1772    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1773    cmp     r0,#0
1774    bne     common_updateProfile
1775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1776    GOTO_OPCODE(ip)                     @ jump to next instruction
1777#else
1778    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1779    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1780    GOTO_OPCODE(ip)                     @ jump to next instruction
1781#endif
1782
1783
1784
1785/* ------------------------------ */
1786    .balign 64
1787.L_OP_IF_LTZ: /* 0x3a */
1788/* File: armv5te/OP_IF_LTZ.S */
1789/* File: armv5te/zcmp.S */
1790    /*
1791     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1792     * fragment that specifies the *reverse* comparison to perform, e.g.
1793     * for "if-le" you would use "gt".
1794     *
1795     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1796     */
1797    /* if-cmp vAA, +BBBB */
1798    mov     r0, rINST, lsr #8           @ r0<- AA
1799    GET_VREG(r2, r0)                    @ r2<- vAA
1800    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1801    cmp     r2, #0                      @ compare (vA, 0)
1802    bge  1f                      @ branch to 1 if comparison failed
1803    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1804    movs    r9, r9, asl #1              @ convert to bytes, check sign
1805    bmi     common_backwardBranch       @ backward branch, do periodic checks
18061:
1807#if defined(WITH_JIT)
1808    GET_JIT_PROF_TABLE(r0)
1809    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1810    cmp     r0,#0
1811    bne     common_updateProfile
1812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1813    GOTO_OPCODE(ip)                     @ jump to next instruction
1814#else
1815    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1817    GOTO_OPCODE(ip)                     @ jump to next instruction
1818#endif
1819
1820
1821
1822/* ------------------------------ */
1823    .balign 64
1824.L_OP_IF_GEZ: /* 0x3b */
1825/* File: armv5te/OP_IF_GEZ.S */
1826/* File: armv5te/zcmp.S */
1827    /*
1828     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1829     * fragment that specifies the *reverse* comparison to perform, e.g.
1830     * for "if-le" you would use "gt".
1831     *
1832     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1833     */
1834    /* if-cmp vAA, +BBBB */
1835    mov     r0, rINST, lsr #8           @ r0<- AA
1836    GET_VREG(r2, r0)                    @ r2<- vAA
1837    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1838    cmp     r2, #0                      @ compare (vA, 0)
1839    blt  1f                      @ branch to 1 if comparison failed
1840    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1841    movs    r9, r9, asl #1              @ convert to bytes, check sign
1842    bmi     common_backwardBranch       @ backward branch, do periodic checks
18431:
1844#if defined(WITH_JIT)
1845    GET_JIT_PROF_TABLE(r0)
1846    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1847    cmp     r0,#0
1848    bne     common_updateProfile
1849    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1850    GOTO_OPCODE(ip)                     @ jump to next instruction
1851#else
1852    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1853    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1854    GOTO_OPCODE(ip)                     @ jump to next instruction
1855#endif
1856
1857
1858
1859/* ------------------------------ */
1860    .balign 64
1861.L_OP_IF_GTZ: /* 0x3c */
1862/* File: armv5te/OP_IF_GTZ.S */
1863/* File: armv5te/zcmp.S */
1864    /*
1865     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1866     * fragment that specifies the *reverse* comparison to perform, e.g.
1867     * for "if-le" you would use "gt".
1868     *
1869     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1870     */
1871    /* if-cmp vAA, +BBBB */
1872    mov     r0, rINST, lsr #8           @ r0<- AA
1873    GET_VREG(r2, r0)                    @ r2<- vAA
1874    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1875    cmp     r2, #0                      @ compare (vA, 0)
1876    ble  1f                      @ branch to 1 if comparison failed
1877    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1878    movs    r9, r9, asl #1              @ convert to bytes, check sign
1879    bmi     common_backwardBranch       @ backward branch, do periodic checks
18801:
1881#if defined(WITH_JIT)
1882    GET_JIT_PROF_TABLE(r0)
1883    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1884    cmp     r0,#0
1885    bne     common_updateProfile
1886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1887    GOTO_OPCODE(ip)                     @ jump to next instruction
1888#else
1889    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1890    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1891    GOTO_OPCODE(ip)                     @ jump to next instruction
1892#endif
1893
1894
1895
1896/* ------------------------------ */
1897    .balign 64
1898.L_OP_IF_LEZ: /* 0x3d */
1899/* File: armv5te/OP_IF_LEZ.S */
1900/* File: armv5te/zcmp.S */
1901    /*
1902     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1903     * fragment that specifies the *reverse* comparison to perform, e.g.
1904     * for "if-le" you would use "gt".
1905     *
1906     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1907     */
1908    /* if-cmp vAA, +BBBB */
1909    mov     r0, rINST, lsr #8           @ r0<- AA
1910    GET_VREG(r2, r0)                    @ r2<- vAA
1911    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1912    cmp     r2, #0                      @ compare (vA, 0)
1913    bgt  1f                      @ branch to 1 if comparison failed
1914    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1915    movs    r9, r9, asl #1              @ convert to bytes, check sign
1916    bmi     common_backwardBranch       @ backward branch, do periodic checks
19171:
1918#if defined(WITH_JIT)
1919    GET_JIT_PROF_TABLE(r0)
1920    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1921    cmp     r0,#0
1922    bne     common_updateProfile
1923    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1924    GOTO_OPCODE(ip)                     @ jump to next instruction
1925#else
1926    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1928    GOTO_OPCODE(ip)                     @ jump to next instruction
1929#endif
1930
1931
1932
1933/* ------------------------------ */
1934    .balign 64
1935.L_OP_UNUSED_3E: /* 0x3e */
1936/* File: armv5te/OP_UNUSED_3E.S */
1937/* File: armv5te/unused.S */
1938    bl      common_abort
1939
1940
1941
1942/* ------------------------------ */
1943    .balign 64
1944.L_OP_UNUSED_3F: /* 0x3f */
1945/* File: armv5te/OP_UNUSED_3F.S */
1946/* File: armv5te/unused.S */
1947    bl      common_abort
1948
1949
1950
1951/* ------------------------------ */
1952    .balign 64
1953.L_OP_UNUSED_40: /* 0x40 */
1954/* File: armv5te/OP_UNUSED_40.S */
1955/* File: armv5te/unused.S */
1956    bl      common_abort
1957
1958
1959
1960/* ------------------------------ */
1961    .balign 64
1962.L_OP_UNUSED_41: /* 0x41 */
1963/* File: armv5te/OP_UNUSED_41.S */
1964/* File: armv5te/unused.S */
1965    bl      common_abort
1966
1967
1968
1969/* ------------------------------ */
1970    .balign 64
1971.L_OP_UNUSED_42: /* 0x42 */
1972/* File: armv5te/OP_UNUSED_42.S */
1973/* File: armv5te/unused.S */
1974    bl      common_abort
1975
1976
1977
1978/* ------------------------------ */
1979    .balign 64
1980.L_OP_UNUSED_43: /* 0x43 */
1981/* File: armv5te/OP_UNUSED_43.S */
1982/* File: armv5te/unused.S */
1983    bl      common_abort
1984
1985
1986
1987/* ------------------------------ */
1988    .balign 64
1989.L_OP_AGET: /* 0x44 */
1990/* File: armv5te/OP_AGET.S */
1991    /*
1992     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1993     *
1994     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1995     * instructions.  We use a pair of FETCH_Bs instead.
1996     *
1997     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1998     */
1999    /* op vAA, vBB, vCC */
2000    FETCH_B(r2, 1, 0)                   @ r2<- BB
2001    mov     r9, rINST, lsr #8           @ r9<- AA
2002    FETCH_B(r3, 1, 1)                   @ r3<- CC
2003    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2004    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2005    cmp     r0, #0                      @ null array object?
2006    beq     common_errNullObject        @ yes, bail
2007    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2008    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2009    cmp     r1, r3                      @ compare unsigned index, length
2010    bcs     common_errArrayIndex        @ index >= length, bail
2011    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2012    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2014    SET_VREG(r2, r9)                    @ vAA<- r2
2015    GOTO_OPCODE(ip)                     @ jump to next instruction
2016
2017
2018/* ------------------------------ */
2019    .balign 64
2020.L_OP_AGET_WIDE: /* 0x45 */
2021/* File: armv5te/OP_AGET_WIDE.S */
2022    /*
2023     * Array get, 64 bits.  vAA <- vBB[vCC].
2024     *
2025     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2026     */
2027    /* aget-wide vAA, vBB, vCC */
2028    FETCH(r0, 1)                        @ r0<- CCBB
2029    mov     r9, rINST, lsr #8           @ r9<- AA
2030    and     r2, r0, #255                @ r2<- BB
2031    mov     r3, r0, lsr #8              @ r3<- CC
2032    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2033    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2034    cmp     r0, #0                      @ null array object?
2035    beq     common_errNullObject        @ yes, bail
2036    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2037    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2038    cmp     r1, r3                      @ compare unsigned index, length
2039    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2040    b       common_errArrayIndex        @ index >= length, bail
2041    @ May want to swap the order of these two branches depending on how the
2042    @ branch prediction (if any) handles conditional forward branches vs.
2043    @ unconditional forward branches.
2044
2045/* ------------------------------ */
2046    .balign 64
2047.L_OP_AGET_OBJECT: /* 0x46 */
2048/* File: armv5te/OP_AGET_OBJECT.S */
2049/* File: armv5te/OP_AGET.S */
2050    /*
2051     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2052     *
2053     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2054     * instructions.  We use a pair of FETCH_Bs instead.
2055     *
2056     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2057     */
2058    /* op vAA, vBB, vCC */
2059    FETCH_B(r2, 1, 0)                   @ r2<- BB
2060    mov     r9, rINST, lsr #8           @ r9<- AA
2061    FETCH_B(r3, 1, 1)                   @ r3<- CC
2062    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2063    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2064    cmp     r0, #0                      @ null array object?
2065    beq     common_errNullObject        @ yes, bail
2066    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2067    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2068    cmp     r1, r3                      @ compare unsigned index, length
2069    bcs     common_errArrayIndex        @ index >= length, bail
2070    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2071    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2072    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2073    SET_VREG(r2, r9)                    @ vAA<- r2
2074    GOTO_OPCODE(ip)                     @ jump to next instruction
2075
2076
2077
2078/* ------------------------------ */
2079    .balign 64
2080.L_OP_AGET_BOOLEAN: /* 0x47 */
2081/* File: armv5te/OP_AGET_BOOLEAN.S */
2082/* File: armv5te/OP_AGET.S */
2083    /*
2084     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2085     *
2086     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2087     * instructions.  We use a pair of FETCH_Bs instead.
2088     *
2089     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2090     */
2091    /* op vAA, vBB, vCC */
2092    FETCH_B(r2, 1, 0)                   @ r2<- BB
2093    mov     r9, rINST, lsr #8           @ r9<- AA
2094    FETCH_B(r3, 1, 1)                   @ r3<- CC
2095    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2096    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2097    cmp     r0, #0                      @ null array object?
2098    beq     common_errNullObject        @ yes, bail
2099    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2100    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2101    cmp     r1, r3                      @ compare unsigned index, length
2102    bcs     common_errArrayIndex        @ index >= length, bail
2103    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2104    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2106    SET_VREG(r2, r9)                    @ vAA<- r2
2107    GOTO_OPCODE(ip)                     @ jump to next instruction
2108
2109
2110
2111/* ------------------------------ */
2112    .balign 64
2113.L_OP_AGET_BYTE: /* 0x48 */
2114/* File: armv5te/OP_AGET_BYTE.S */
2115/* File: armv5te/OP_AGET.S */
2116    /*
2117     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2118     *
2119     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2120     * instructions.  We use a pair of FETCH_Bs instead.
2121     *
2122     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2123     */
2124    /* op vAA, vBB, vCC */
2125    FETCH_B(r2, 1, 0)                   @ r2<- BB
2126    mov     r9, rINST, lsr #8           @ r9<- AA
2127    FETCH_B(r3, 1, 1)                   @ r3<- CC
2128    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2129    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2130    cmp     r0, #0                      @ null array object?
2131    beq     common_errNullObject        @ yes, bail
2132    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2133    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2134    cmp     r1, r3                      @ compare unsigned index, length
2135    bcs     common_errArrayIndex        @ index >= length, bail
2136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2137    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2138    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2139    SET_VREG(r2, r9)                    @ vAA<- r2
2140    GOTO_OPCODE(ip)                     @ jump to next instruction
2141
2142
2143
2144/* ------------------------------ */
2145    .balign 64
2146.L_OP_AGET_CHAR: /* 0x49 */
2147/* File: armv5te/OP_AGET_CHAR.S */
2148/* File: armv5te/OP_AGET.S */
2149    /*
2150     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2151     *
2152     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2153     * instructions.  We use a pair of FETCH_Bs instead.
2154     *
2155     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2156     */
2157    /* op vAA, vBB, vCC */
2158    FETCH_B(r2, 1, 0)                   @ r2<- BB
2159    mov     r9, rINST, lsr #8           @ r9<- AA
2160    FETCH_B(r3, 1, 1)                   @ r3<- CC
2161    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2162    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2163    cmp     r0, #0                      @ null array object?
2164    beq     common_errNullObject        @ yes, bail
2165    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2166    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2167    cmp     r1, r3                      @ compare unsigned index, length
2168    bcs     common_errArrayIndex        @ index >= length, bail
2169    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2170    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2172    SET_VREG(r2, r9)                    @ vAA<- r2
2173    GOTO_OPCODE(ip)                     @ jump to next instruction
2174
2175
2176
2177/* ------------------------------ */
2178    .balign 64
2179.L_OP_AGET_SHORT: /* 0x4a */
2180/* File: armv5te/OP_AGET_SHORT.S */
2181/* File: armv5te/OP_AGET.S */
2182    /*
2183     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2184     *
2185     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2186     * instructions.  We use a pair of FETCH_Bs instead.
2187     *
2188     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2189     */
2190    /* op vAA, vBB, vCC */
2191    FETCH_B(r2, 1, 0)                   @ r2<- BB
2192    mov     r9, rINST, lsr #8           @ r9<- AA
2193    FETCH_B(r3, 1, 1)                   @ r3<- CC
2194    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2195    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2196    cmp     r0, #0                      @ null array object?
2197    beq     common_errNullObject        @ yes, bail
2198    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2199    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2200    cmp     r1, r3                      @ compare unsigned index, length
2201    bcs     common_errArrayIndex        @ index >= length, bail
2202    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2203    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2204    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2205    SET_VREG(r2, r9)                    @ vAA<- r2
2206    GOTO_OPCODE(ip)                     @ jump to next instruction
2207
2208
2209
2210/* ------------------------------ */
2211    .balign 64
2212.L_OP_APUT: /* 0x4b */
2213/* File: armv5te/OP_APUT.S */
2214    /*
2215     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2216     *
2217     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2218     * instructions.  We use a pair of FETCH_Bs instead.
2219     *
2220     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2221     */
2222    /* op vAA, vBB, vCC */
2223    FETCH_B(r2, 1, 0)                   @ r2<- BB
2224    mov     r9, rINST, lsr #8           @ r9<- AA
2225    FETCH_B(r3, 1, 1)                   @ r3<- CC
2226    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2227    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2228    cmp     r0, #0                      @ null array object?
2229    beq     common_errNullObject        @ yes, bail
2230    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2231    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2232    cmp     r1, r3                      @ compare unsigned index, length
2233    bcs     common_errArrayIndex        @ index >= length, bail
2234    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2235    GET_VREG(r2, r9)                    @ r2<- vAA
2236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2237    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2238    GOTO_OPCODE(ip)                     @ jump to next instruction
2239
2240
2241/* ------------------------------ */
2242    .balign 64
2243.L_OP_APUT_WIDE: /* 0x4c */
2244/* File: armv5te/OP_APUT_WIDE.S */
2245    /*
2246     * Array put, 64 bits.  vBB[vCC] <- vAA.
2247     *
2248     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2249     */
2250    /* aput-wide vAA, vBB, vCC */
2251    FETCH(r0, 1)                        @ r0<- CCBB
2252    mov     r9, rINST, lsr #8           @ r9<- AA
2253    and     r2, r0, #255                @ r2<- BB
2254    mov     r3, r0, lsr #8              @ r3<- CC
2255    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2256    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2257    cmp     r0, #0                      @ null array object?
2258    beq     common_errNullObject        @ yes, bail
2259    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2260    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2261    cmp     r1, r3                      @ compare unsigned index, length
2262    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2263    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2264    b       common_errArrayIndex        @ index >= length, bail
2265    @ May want to swap the order of these two branches depending on how the
2266    @ branch prediction (if any) handles conditional forward branches vs.
2267    @ unconditional forward branches.
2268
2269/* ------------------------------ */
2270    .balign 64
2271.L_OP_APUT_OBJECT: /* 0x4d */
2272/* File: armv5te/OP_APUT_OBJECT.S */
2273    /*
2274     * Store an object into an array.  vBB[vCC] <- vAA.
2275     *
2276     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2277     * instructions.  We use a pair of FETCH_Bs instead.
2278     */
2279    /* op vAA, vBB, vCC */
2280    FETCH(r0, 1)                        @ r0<- CCBB
2281    mov     r9, rINST, lsr #8           @ r9<- AA
2282    and     r2, r0, #255                @ r2<- BB
2283    mov     r3, r0, lsr #8              @ r3<- CC
2284    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2285    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2286    cmp     r1, #0                      @ null array object?
2287    GET_VREG(r9, r9)                    @ r9<- vAA
2288    beq     common_errNullObject        @ yes, bail
2289    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2290    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2291    cmp     r0, r3                      @ compare unsigned index, length
2292    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2293    b       common_errArrayIndex        @ index >= length, bail
2294
2295
2296/* ------------------------------ */
2297    .balign 64
2298.L_OP_APUT_BOOLEAN: /* 0x4e */
2299/* File: armv5te/OP_APUT_BOOLEAN.S */
2300/* File: armv5te/OP_APUT.S */
2301    /*
2302     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2303     *
2304     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2305     * instructions.  We use a pair of FETCH_Bs instead.
2306     *
2307     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2308     */
2309    /* op vAA, vBB, vCC */
2310    FETCH_B(r2, 1, 0)                   @ r2<- BB
2311    mov     r9, rINST, lsr #8           @ r9<- AA
2312    FETCH_B(r3, 1, 1)                   @ r3<- CC
2313    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2314    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2315    cmp     r0, #0                      @ null array object?
2316    beq     common_errNullObject        @ yes, bail
2317    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2318    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2319    cmp     r1, r3                      @ compare unsigned index, length
2320    bcs     common_errArrayIndex        @ index >= length, bail
2321    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2322    GET_VREG(r2, r9)                    @ r2<- vAA
2323    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2324    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2325    GOTO_OPCODE(ip)                     @ jump to next instruction
2326
2327
2328
2329/* ------------------------------ */
2330    .balign 64
2331.L_OP_APUT_BYTE: /* 0x4f */
2332/* File: armv5te/OP_APUT_BYTE.S */
2333/* File: armv5te/OP_APUT.S */
2334    /*
2335     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2336     *
2337     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2338     * instructions.  We use a pair of FETCH_Bs instead.
2339     *
2340     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2341     */
2342    /* op vAA, vBB, vCC */
2343    FETCH_B(r2, 1, 0)                   @ r2<- BB
2344    mov     r9, rINST, lsr #8           @ r9<- AA
2345    FETCH_B(r3, 1, 1)                   @ r3<- CC
2346    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2347    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2348    cmp     r0, #0                      @ null array object?
2349    beq     common_errNullObject        @ yes, bail
2350    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2351    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2352    cmp     r1, r3                      @ compare unsigned index, length
2353    bcs     common_errArrayIndex        @ index >= length, bail
2354    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2355    GET_VREG(r2, r9)                    @ r2<- vAA
2356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2357    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2358    GOTO_OPCODE(ip)                     @ jump to next instruction
2359
2360
2361
2362/* ------------------------------ */
2363    .balign 64
2364.L_OP_APUT_CHAR: /* 0x50 */
2365/* File: armv5te/OP_APUT_CHAR.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/* ------------------------------ */
2396    .balign 64
2397.L_OP_APUT_SHORT: /* 0x51 */
2398/* File: armv5te/OP_APUT_SHORT.S */
2399/* File: armv5te/OP_APUT.S */
2400    /*
2401     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2402     *
2403     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2404     * instructions.  We use a pair of FETCH_Bs instead.
2405     *
2406     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2407     */
2408    /* op vAA, vBB, vCC */
2409    FETCH_B(r2, 1, 0)                   @ r2<- BB
2410    mov     r9, rINST, lsr #8           @ r9<- AA
2411    FETCH_B(r3, 1, 1)                   @ r3<- CC
2412    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2413    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2414    cmp     r0, #0                      @ null array object?
2415    beq     common_errNullObject        @ yes, bail
2416    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2417    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2418    cmp     r1, r3                      @ compare unsigned index, length
2419    bcs     common_errArrayIndex        @ index >= length, bail
2420    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2421    GET_VREG(r2, r9)                    @ r2<- vAA
2422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2423    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2424    GOTO_OPCODE(ip)                     @ jump to next instruction
2425
2426
2427
2428/* ------------------------------ */
2429    .balign 64
2430.L_OP_IGET: /* 0x52 */
2431/* File: armv6t2/OP_IGET.S */
2432    /*
2433     * General 32-bit instance field get.
2434     *
2435     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2436     */
2437    /* op vA, vB, field@CCCC */
2438    mov     r0, rINST, lsr #12          @ r0<- B
2439    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2440    FETCH(r1, 1)                        @ r1<- field ref CCCC
2441    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2442    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2443    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2444    cmp     r0, #0                      @ is resolved entry null?
2445    bne     .LOP_IGET_finish          @ no, already resolved
24468:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2447    EXPORT_PC()                         @ resolve() could throw
2448    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2449    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2450    cmp     r0, #0
2451    bne     .LOP_IGET_finish
2452    b       common_exceptionThrown
2453
2454/* ------------------------------ */
2455    .balign 64
2456.L_OP_IGET_WIDE: /* 0x53 */
2457/* File: armv6t2/OP_IGET_WIDE.S */
2458    /*
2459     * Wide 32-bit instance field get.
2460     */
2461    /* iget-wide vA, vB, field@CCCC */
2462    mov     r0, rINST, lsr #12          @ r0<- B
2463    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2464    FETCH(r1, 1)                        @ r1<- field ref CCCC
2465    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2466    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2467    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2468    cmp     r0, #0                      @ is resolved entry null?
2469    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24708:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2471    EXPORT_PC()                         @ resolve() could throw
2472    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2473    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2474    cmp     r0, #0
2475    bne     .LOP_IGET_WIDE_finish
2476    b       common_exceptionThrown
2477
2478/* ------------------------------ */
2479    .balign 64
2480.L_OP_IGET_OBJECT: /* 0x54 */
2481/* File: armv5te/OP_IGET_OBJECT.S */
2482/* File: armv5te/OP_IGET.S */
2483    /*
2484     * General 32-bit instance field get.
2485     *
2486     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2487     */
2488    /* op vA, vB, field@CCCC */
2489    mov     r0, rINST, lsr #12          @ r0<- B
2490    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2491    FETCH(r1, 1)                        @ r1<- field ref CCCC
2492    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2493    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2494    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2495    cmp     r0, #0                      @ is resolved entry null?
2496    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24978:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2498    EXPORT_PC()                         @ resolve() could throw
2499    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2500    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2501    cmp     r0, #0
2502    bne     .LOP_IGET_OBJECT_finish
2503    b       common_exceptionThrown
2504
2505
2506/* ------------------------------ */
2507    .balign 64
2508.L_OP_IGET_BOOLEAN: /* 0x55 */
2509/* File: armv5te/OP_IGET_BOOLEAN.S */
2510@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2511/* File: armv5te/OP_IGET.S */
2512    /*
2513     * General 32-bit instance field get.
2514     *
2515     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2516     */
2517    /* op vA, vB, field@CCCC */
2518    mov     r0, rINST, lsr #12          @ r0<- B
2519    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2520    FETCH(r1, 1)                        @ r1<- field ref CCCC
2521    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2522    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2523    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2524    cmp     r0, #0                      @ is resolved entry null?
2525    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25268:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2527    EXPORT_PC()                         @ resolve() could throw
2528    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2529    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2530    cmp     r0, #0
2531    bne     .LOP_IGET_BOOLEAN_finish
2532    b       common_exceptionThrown
2533
2534
2535/* ------------------------------ */
2536    .balign 64
2537.L_OP_IGET_BYTE: /* 0x56 */
2538/* File: armv5te/OP_IGET_BYTE.S */
2539@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2540/* File: armv5te/OP_IGET.S */
2541    /*
2542     * General 32-bit instance field get.
2543     *
2544     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2545     */
2546    /* op vA, vB, field@CCCC */
2547    mov     r0, rINST, lsr #12          @ r0<- B
2548    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2549    FETCH(r1, 1)                        @ r1<- field ref CCCC
2550    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2551    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2552    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2553    cmp     r0, #0                      @ is resolved entry null?
2554    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25558:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2556    EXPORT_PC()                         @ resolve() could throw
2557    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2558    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2559    cmp     r0, #0
2560    bne     .LOP_IGET_BYTE_finish
2561    b       common_exceptionThrown
2562
2563
2564/* ------------------------------ */
2565    .balign 64
2566.L_OP_IGET_CHAR: /* 0x57 */
2567/* File: armv5te/OP_IGET_CHAR.S */
2568@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2569/* File: armv5te/OP_IGET.S */
2570    /*
2571     * General 32-bit instance field get.
2572     *
2573     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2574     */
2575    /* op vA, vB, field@CCCC */
2576    mov     r0, rINST, lsr #12          @ r0<- B
2577    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2578    FETCH(r1, 1)                        @ r1<- field ref CCCC
2579    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2580    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2581    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2582    cmp     r0, #0                      @ is resolved entry null?
2583    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25848:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2585    EXPORT_PC()                         @ resolve() could throw
2586    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2587    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2588    cmp     r0, #0
2589    bne     .LOP_IGET_CHAR_finish
2590    b       common_exceptionThrown
2591
2592
2593/* ------------------------------ */
2594    .balign 64
2595.L_OP_IGET_SHORT: /* 0x58 */
2596/* File: armv5te/OP_IGET_SHORT.S */
2597@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2598/* File: armv5te/OP_IGET.S */
2599    /*
2600     * General 32-bit instance field get.
2601     *
2602     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2603     */
2604    /* op vA, vB, field@CCCC */
2605    mov     r0, rINST, lsr #12          @ r0<- B
2606    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2607    FETCH(r1, 1)                        @ r1<- field ref CCCC
2608    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2609    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2610    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2611    cmp     r0, #0                      @ is resolved entry null?
2612    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2614    EXPORT_PC()                         @ resolve() could throw
2615    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2616    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2617    cmp     r0, #0
2618    bne     .LOP_IGET_SHORT_finish
2619    b       common_exceptionThrown
2620
2621
2622/* ------------------------------ */
2623    .balign 64
2624.L_OP_IPUT: /* 0x59 */
2625/* File: armv6t2/OP_IPUT.S */
2626    /*
2627     * General 32-bit instance field put.
2628     *
2629     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2630     */
2631    /* op vA, vB, field@CCCC */
2632    mov     r0, rINST, lsr #12          @ r0<- B
2633    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2634    FETCH(r1, 1)                        @ r1<- field ref CCCC
2635    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2636    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2637    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2638    cmp     r0, #0                      @ is resolved entry null?
2639    bne     .LOP_IPUT_finish          @ no, already resolved
26408:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2641    EXPORT_PC()                         @ resolve() could throw
2642    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2643    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2644    cmp     r0, #0                      @ success?
2645    bne     .LOP_IPUT_finish          @ yes, finish up
2646    b       common_exceptionThrown
2647
2648/* ------------------------------ */
2649    .balign 64
2650.L_OP_IPUT_WIDE: /* 0x5a */
2651/* File: armv6t2/OP_IPUT_WIDE.S */
2652    /* iput-wide vA, vB, field@CCCC */
2653    mov     r0, rINST, lsr #12          @ r0<- B
2654    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2655    FETCH(r1, 1)                        @ r1<- field ref CCCC
2656    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2657    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2658    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2659    cmp     r0, #0                      @ is resolved entry null?
2660    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26618:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2662    EXPORT_PC()                         @ resolve() could throw
2663    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2664    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2665    cmp     r0, #0                      @ success?
2666    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2667    b       common_exceptionThrown
2668
2669/* ------------------------------ */
2670    .balign 64
2671.L_OP_IPUT_OBJECT: /* 0x5b */
2672/* File: armv5te/OP_IPUT_OBJECT.S */
2673/* File: armv5te/OP_IPUT.S */
2674    /*
2675     * General 32-bit instance field put.
2676     *
2677     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2678     */
2679    /* op vA, vB, field@CCCC */
2680    mov     r0, rINST, lsr #12          @ r0<- B
2681    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2682    FETCH(r1, 1)                        @ r1<- field ref CCCC
2683    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2684    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2685    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2686    cmp     r0, #0                      @ is resolved entry null?
2687    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26888:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2689    EXPORT_PC()                         @ resolve() could throw
2690    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2691    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2692    cmp     r0, #0                      @ success?
2693    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2694    b       common_exceptionThrown
2695
2696
2697/* ------------------------------ */
2698    .balign 64
2699.L_OP_IPUT_BOOLEAN: /* 0x5c */
2700/* File: armv5te/OP_IPUT_BOOLEAN.S */
2701@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2702/* File: armv5te/OP_IPUT.S */
2703    /*
2704     * General 32-bit instance field put.
2705     *
2706     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2707     */
2708    /* op vA, vB, field@CCCC */
2709    mov     r0, rINST, lsr #12          @ r0<- B
2710    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2711    FETCH(r1, 1)                        @ r1<- field ref CCCC
2712    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2713    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2714    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2715    cmp     r0, #0                      @ is resolved entry null?
2716    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27178:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2718    EXPORT_PC()                         @ resolve() could throw
2719    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2720    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2721    cmp     r0, #0                      @ success?
2722    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2723    b       common_exceptionThrown
2724
2725
2726/* ------------------------------ */
2727    .balign 64
2728.L_OP_IPUT_BYTE: /* 0x5d */
2729/* File: armv5te/OP_IPUT_BYTE.S */
2730@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2731/* File: armv5te/OP_IPUT.S */
2732    /*
2733     * General 32-bit instance field put.
2734     *
2735     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2736     */
2737    /* op vA, vB, field@CCCC */
2738    mov     r0, rINST, lsr #12          @ r0<- B
2739    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2740    FETCH(r1, 1)                        @ r1<- field ref CCCC
2741    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2742    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2743    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2744    cmp     r0, #0                      @ is resolved entry null?
2745    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27468:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2747    EXPORT_PC()                         @ resolve() could throw
2748    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2749    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2750    cmp     r0, #0                      @ success?
2751    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2752    b       common_exceptionThrown
2753
2754
2755/* ------------------------------ */
2756    .balign 64
2757.L_OP_IPUT_CHAR: /* 0x5e */
2758/* File: armv5te/OP_IPUT_CHAR.S */
2759@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2760/* File: armv5te/OP_IPUT.S */
2761    /*
2762     * General 32-bit instance field put.
2763     *
2764     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2765     */
2766    /* op vA, vB, field@CCCC */
2767    mov     r0, rINST, lsr #12          @ r0<- B
2768    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2769    FETCH(r1, 1)                        @ r1<- field ref CCCC
2770    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2771    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2772    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2773    cmp     r0, #0                      @ is resolved entry null?
2774    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27758:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2776    EXPORT_PC()                         @ resolve() could throw
2777    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2778    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2779    cmp     r0, #0                      @ success?
2780    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2781    b       common_exceptionThrown
2782
2783
2784/* ------------------------------ */
2785    .balign 64
2786.L_OP_IPUT_SHORT: /* 0x5f */
2787/* File: armv5te/OP_IPUT_SHORT.S */
2788@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2789/* File: armv5te/OP_IPUT.S */
2790    /*
2791     * General 32-bit instance field put.
2792     *
2793     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2794     */
2795    /* op vA, vB, field@CCCC */
2796    mov     r0, rINST, lsr #12          @ r0<- B
2797    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2798    FETCH(r1, 1)                        @ r1<- field ref CCCC
2799    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2800    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2801    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2802    cmp     r0, #0                      @ is resolved entry null?
2803    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28048:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2805    EXPORT_PC()                         @ resolve() could throw
2806    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2807    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2808    cmp     r0, #0                      @ success?
2809    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2810    b       common_exceptionThrown
2811
2812
2813/* ------------------------------ */
2814    .balign 64
2815.L_OP_SGET: /* 0x60 */
2816/* File: armv5te/OP_SGET.S */
2817    /*
2818     * General 32-bit SGET handler.
2819     *
2820     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2821     */
2822    /* op vAA, field@BBBB */
2823    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2824    FETCH(r1, 1)                        @ r1<- field ref BBBB
2825    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2826    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2827    cmp     r0, #0                      @ is resolved entry null?
2828    beq     .LOP_SGET_resolve         @ yes, do resolve
2829.LOP_SGET_finish: @ field ptr in r0
2830    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2831    mov     r2, rINST, lsr #8           @ r2<- AA
2832    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2833    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2834    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2835    GOTO_OPCODE(ip)                     @ jump to next instruction
2836
2837/* ------------------------------ */
2838    .balign 64
2839.L_OP_SGET_WIDE: /* 0x61 */
2840/* File: armv5te/OP_SGET_WIDE.S */
2841    /*
2842     * 64-bit SGET handler.
2843     */
2844    /* sget-wide vAA, field@BBBB */
2845    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2846    FETCH(r1, 1)                        @ r1<- field ref BBBB
2847    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2848    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2849    cmp     r0, #0                      @ is resolved entry null?
2850    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2851.LOP_SGET_WIDE_finish:
2852    mov     r1, rINST, lsr #8           @ r1<- AA
2853    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2854    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2855    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2856    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2857    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2858    GOTO_OPCODE(ip)                     @ jump to next instruction
2859
2860/* ------------------------------ */
2861    .balign 64
2862.L_OP_SGET_OBJECT: /* 0x62 */
2863/* File: armv5te/OP_SGET_OBJECT.S */
2864/* File: armv5te/OP_SGET.S */
2865    /*
2866     * General 32-bit SGET handler.
2867     *
2868     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2869     */
2870    /* op vAA, field@BBBB */
2871    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2872    FETCH(r1, 1)                        @ r1<- field ref BBBB
2873    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2874    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2875    cmp     r0, #0                      @ is resolved entry null?
2876    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2877.LOP_SGET_OBJECT_finish: @ field ptr in r0
2878    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
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_BOOLEAN: /* 0x63 */
2889/* File: armv5te/OP_SGET_BOOLEAN.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_BOOLEAN_resolve         @ yes, do resolve
2903.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2904    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2905    mov     r2, rINST, lsr #8           @ r2<- AA
2906    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2907    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2909    GOTO_OPCODE(ip)                     @ jump to next instruction
2910
2911
2912/* ------------------------------ */
2913    .balign 64
2914.L_OP_SGET_BYTE: /* 0x64 */
2915/* File: armv5te/OP_SGET_BYTE.S */
2916/* File: armv5te/OP_SGET.S */
2917    /*
2918     * General 32-bit SGET handler.
2919     *
2920     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2921     */
2922    /* op vAA, field@BBBB */
2923    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2924    FETCH(r1, 1)                        @ r1<- field ref BBBB
2925    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2926    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2927    cmp     r0, #0                      @ is resolved entry null?
2928    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2929.LOP_SGET_BYTE_finish: @ field ptr in r0
2930    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2931    mov     r2, rINST, lsr #8           @ r2<- AA
2932    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2933    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2935    GOTO_OPCODE(ip)                     @ jump to next instruction
2936
2937
2938/* ------------------------------ */
2939    .balign 64
2940.L_OP_SGET_CHAR: /* 0x65 */
2941/* File: armv5te/OP_SGET_CHAR.S */
2942/* File: armv5te/OP_SGET.S */
2943    /*
2944     * General 32-bit SGET handler.
2945     *
2946     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2947     */
2948    /* op vAA, field@BBBB */
2949    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2950    FETCH(r1, 1)                        @ r1<- field ref BBBB
2951    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2952    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2953    cmp     r0, #0                      @ is resolved entry null?
2954    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2955.LOP_SGET_CHAR_finish: @ field ptr in r0
2956    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2957    mov     r2, rINST, lsr #8           @ r2<- AA
2958    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2959    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2961    GOTO_OPCODE(ip)                     @ jump to next instruction
2962
2963
2964/* ------------------------------ */
2965    .balign 64
2966.L_OP_SGET_SHORT: /* 0x66 */
2967/* File: armv5te/OP_SGET_SHORT.S */
2968/* File: armv5te/OP_SGET.S */
2969    /*
2970     * General 32-bit SGET handler.
2971     *
2972     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2973     */
2974    /* op vAA, field@BBBB */
2975    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2976    FETCH(r1, 1)                        @ r1<- field ref BBBB
2977    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2978    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2979    cmp     r0, #0                      @ is resolved entry null?
2980    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2981.LOP_SGET_SHORT_finish: @ field ptr in r0
2982    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2983    mov     r2, rINST, lsr #8           @ r2<- AA
2984    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2985    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2987    GOTO_OPCODE(ip)                     @ jump to next instruction
2988
2989
2990/* ------------------------------ */
2991    .balign 64
2992.L_OP_SPUT: /* 0x67 */
2993/* File: armv5te/OP_SPUT.S */
2994    /*
2995     * General 32-bit SPUT handler.
2996     *
2997     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2998     */
2999    /* op vAA, field@BBBB */
3000    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3001    FETCH(r1, 1)                        @ r1<- field ref BBBB
3002    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3003    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3004    cmp     r0, #0                      @ is resolved entry null?
3005    beq     .LOP_SPUT_resolve         @ yes, do resolve
3006.LOP_SPUT_finish:   @ field ptr in r0
3007    mov     r2, rINST, lsr #8           @ r2<- AA
3008    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3009    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3010    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3011    str     r1, [r0, #offStaticField_value] @ field<- vAA
3012    GOTO_OPCODE(ip)                     @ jump to next instruction
3013
3014/* ------------------------------ */
3015    .balign 64
3016.L_OP_SPUT_WIDE: /* 0x68 */
3017/* File: armv5te/OP_SPUT_WIDE.S */
3018    /*
3019     * 64-bit SPUT handler.
3020     */
3021    /* sput-wide vAA, field@BBBB */
3022    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3023    FETCH(r1, 1)                        @ r1<- field ref BBBB
3024    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3025    mov     r9, rINST, lsr #8           @ r9<- AA
3026    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3027    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3028    cmp     r0, #0                      @ is resolved entry null?
3029    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3030.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3031    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3032    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3033    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3034    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3035    GOTO_OPCODE(ip)                     @ jump to next instruction
3036
3037/* ------------------------------ */
3038    .balign 64
3039.L_OP_SPUT_OBJECT: /* 0x69 */
3040/* File: armv5te/OP_SPUT_OBJECT.S */
3041/* File: armv5te/OP_SPUT.S */
3042    /*
3043     * General 32-bit SPUT handler.
3044     *
3045     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3046     */
3047    /* op vAA, field@BBBB */
3048    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3049    FETCH(r1, 1)                        @ r1<- field ref BBBB
3050    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3051    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3052    cmp     r0, #0                      @ is resolved entry null?
3053    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3054.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3055    mov     r2, rINST, lsr #8           @ r2<- AA
3056    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3057    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3058    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3059    str     r1, [r0, #offStaticField_value] @ field<- vAA
3060    GOTO_OPCODE(ip)                     @ jump to next instruction
3061
3062
3063/* ------------------------------ */
3064    .balign 64
3065.L_OP_SPUT_BOOLEAN: /* 0x6a */
3066/* File: armv5te/OP_SPUT_BOOLEAN.S */
3067/* File: armv5te/OP_SPUT.S */
3068    /*
3069     * General 32-bit SPUT handler.
3070     *
3071     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3072     */
3073    /* op vAA, field@BBBB */
3074    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3075    FETCH(r1, 1)                        @ r1<- field ref BBBB
3076    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3077    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3078    cmp     r0, #0                      @ is resolved entry null?
3079    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3080.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3081    mov     r2, rINST, lsr #8           @ r2<- AA
3082    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3083    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3084    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3085    str     r1, [r0, #offStaticField_value] @ field<- vAA
3086    GOTO_OPCODE(ip)                     @ jump to next instruction
3087
3088
3089/* ------------------------------ */
3090    .balign 64
3091.L_OP_SPUT_BYTE: /* 0x6b */
3092/* File: armv5te/OP_SPUT_BYTE.S */
3093/* File: armv5te/OP_SPUT.S */
3094    /*
3095     * General 32-bit SPUT handler.
3096     *
3097     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3098     */
3099    /* op vAA, field@BBBB */
3100    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3101    FETCH(r1, 1)                        @ r1<- field ref BBBB
3102    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3103    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3104    cmp     r0, #0                      @ is resolved entry null?
3105    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3106.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3107    mov     r2, rINST, lsr #8           @ r2<- AA
3108    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3109    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3110    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3111    str     r1, [r0, #offStaticField_value] @ field<- vAA
3112    GOTO_OPCODE(ip)                     @ jump to next instruction
3113
3114
3115/* ------------------------------ */
3116    .balign 64
3117.L_OP_SPUT_CHAR: /* 0x6c */
3118/* File: armv5te/OP_SPUT_CHAR.S */
3119/* File: armv5te/OP_SPUT.S */
3120    /*
3121     * General 32-bit SPUT handler.
3122     *
3123     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3124     */
3125    /* op vAA, field@BBBB */
3126    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3127    FETCH(r1, 1)                        @ r1<- field ref BBBB
3128    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3129    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3130    cmp     r0, #0                      @ is resolved entry null?
3131    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3132.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3133    mov     r2, rINST, lsr #8           @ r2<- AA
3134    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3135    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3136    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3137    str     r1, [r0, #offStaticField_value] @ field<- vAA
3138    GOTO_OPCODE(ip)                     @ jump to next instruction
3139
3140
3141/* ------------------------------ */
3142    .balign 64
3143.L_OP_SPUT_SHORT: /* 0x6d */
3144/* File: armv5te/OP_SPUT_SHORT.S */
3145/* File: armv5te/OP_SPUT.S */
3146    /*
3147     * General 32-bit SPUT handler.
3148     *
3149     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3150     */
3151    /* op vAA, field@BBBB */
3152    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3153    FETCH(r1, 1)                        @ r1<- field ref BBBB
3154    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3155    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3156    cmp     r0, #0                      @ is resolved entry null?
3157    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3158.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3159    mov     r2, rINST, lsr #8           @ r2<- AA
3160    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3161    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3162    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3163    str     r1, [r0, #offStaticField_value] @ field<- vAA
3164    GOTO_OPCODE(ip)                     @ jump to next instruction
3165
3166
3167/* ------------------------------ */
3168    .balign 64
3169.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3170/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3171    /*
3172     * Handle a virtual method call.
3173     *
3174     * for: invoke-virtual, invoke-virtual/range
3175     */
3176    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3177    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3178    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3179    FETCH(r1, 1)                        @ r1<- BBBB
3180    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3181    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3182    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3183    .if     (!0)
3184    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3185    .endif
3186    cmp     r0, #0                      @ already resolved?
3187    EXPORT_PC()                         @ must export for invoke
3188    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3189    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3190    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3191    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3192    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3193    cmp     r0, #0                      @ got null?
3194    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3195    b       common_exceptionThrown      @ yes, handle exception
3196
3197/* ------------------------------ */
3198    .balign 64
3199.L_OP_INVOKE_SUPER: /* 0x6f */
3200/* File: armv5te/OP_INVOKE_SUPER.S */
3201    /*
3202     * Handle a "super" method call.
3203     *
3204     * for: invoke-super, invoke-super/range
3205     */
3206    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3207    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3208    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3209    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3210    .if     (!0)
3211    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3212    .endif
3213    FETCH(r1, 1)                        @ r1<- BBBB
3214    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3215    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3216    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3217    cmp     r2, #0                      @ null "this"?
3218    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3219    beq     common_errNullObject        @ null "this", throw exception
3220    cmp     r0, #0                      @ already resolved?
3221    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3222    EXPORT_PC()                         @ must export for invoke
3223    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3224    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3225
3226/* ------------------------------ */
3227    .balign 64
3228.L_OP_INVOKE_DIRECT: /* 0x70 */
3229/* File: armv5te/OP_INVOKE_DIRECT.S */
3230    /*
3231     * Handle a direct method call.
3232     *
3233     * (We could defer the "is 'this' pointer null" test to the common
3234     * method invocation code, and use a flag to indicate that static
3235     * calls don't count.  If we do this as part of copying the arguments
3236     * out we could avoiding loading the first arg twice.)
3237     *
3238     * for: invoke-direct, invoke-direct/range
3239     */
3240    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3241    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3242    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3243    FETCH(r1, 1)                        @ r1<- BBBB
3244    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3245    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3246    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3247    .if     (!0)
3248    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3249    .endif
3250    cmp     r0, #0                      @ already resolved?
3251    EXPORT_PC()                         @ must export for invoke
3252    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3253    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3254.LOP_INVOKE_DIRECT_finish:
3255    cmp     r2, #0                      @ null "this" ref?
3256    bne     common_invokeMethodNoRange   @ no, continue on
3257    b       common_errNullObject        @ yes, throw exception
3258
3259/* ------------------------------ */
3260    .balign 64
3261.L_OP_INVOKE_STATIC: /* 0x71 */
3262/* File: armv5te/OP_INVOKE_STATIC.S */
3263    /*
3264     * Handle a static method call.
3265     *
3266     * for: invoke-static, invoke-static/range
3267     */
3268    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3269    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3270    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3271    FETCH(r1, 1)                        @ r1<- BBBB
3272    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3273    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3274    cmp     r0, #0                      @ already resolved?
3275    EXPORT_PC()                         @ must export for invoke
3276    bne     common_invokeMethodNoRange @ yes, continue on
32770:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3278    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3279    mov     r2, #METHOD_STATIC          @ resolver method type
3280    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3281    cmp     r0, #0                      @ got null?
3282    bne     common_invokeMethodNoRange @ no, continue
3283    b       common_exceptionThrown      @ yes, handle exception
3284
3285
3286/* ------------------------------ */
3287    .balign 64
3288.L_OP_INVOKE_INTERFACE: /* 0x72 */
3289/* File: armv5te/OP_INVOKE_INTERFACE.S */
3290    /*
3291     * Handle an interface method call.
3292     *
3293     * for: invoke-interface, invoke-interface/range
3294     */
3295    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3296    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3297    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3298    FETCH(r1, 1)                        @ r1<- BBBB
3299    .if     (!0)
3300    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3301    .endif
3302    EXPORT_PC()                         @ must export for invoke
3303    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3304    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3305    cmp     r0, #0                      @ null obj?
3306    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3307    beq     common_errNullObject        @ yes, fail
3308    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3309    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3310    cmp     r0, #0                      @ failed?
3311    beq     common_exceptionThrown      @ yes, handle exception
3312    b       common_invokeMethodNoRange @ jump to common handler
3313
3314
3315/* ------------------------------ */
3316    .balign 64
3317.L_OP_UNUSED_73: /* 0x73 */
3318/* File: armv5te/OP_UNUSED_73.S */
3319/* File: armv5te/unused.S */
3320    bl      common_abort
3321
3322
3323
3324/* ------------------------------ */
3325    .balign 64
3326.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3327/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3328/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3329    /*
3330     * Handle a virtual method call.
3331     *
3332     * for: invoke-virtual, invoke-virtual/range
3333     */
3334    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3335    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3336    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3337    FETCH(r1, 1)                        @ r1<- BBBB
3338    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3339    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3340    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3341    .if     (!1)
3342    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3343    .endif
3344    cmp     r0, #0                      @ already resolved?
3345    EXPORT_PC()                         @ must export for invoke
3346    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3347    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3348    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3349    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3350    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3351    cmp     r0, #0                      @ got null?
3352    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3353    b       common_exceptionThrown      @ yes, handle exception
3354
3355
3356/* ------------------------------ */
3357    .balign 64
3358.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3359/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3360/* File: armv5te/OP_INVOKE_SUPER.S */
3361    /*
3362     * Handle a "super" method call.
3363     *
3364     * for: invoke-super, invoke-super/range
3365     */
3366    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3367    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3368    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3369    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3370    .if     (!1)
3371    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3372    .endif
3373    FETCH(r1, 1)                        @ r1<- BBBB
3374    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3375    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3376    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3377    cmp     r2, #0                      @ null "this"?
3378    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3379    beq     common_errNullObject        @ null "this", throw exception
3380    cmp     r0, #0                      @ already resolved?
3381    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3382    EXPORT_PC()                         @ must export for invoke
3383    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3384    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3385
3386
3387/* ------------------------------ */
3388    .balign 64
3389.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3390/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3391/* File: armv5te/OP_INVOKE_DIRECT.S */
3392    /*
3393     * Handle a direct method call.
3394     *
3395     * (We could defer the "is 'this' pointer null" test to the common
3396     * method invocation code, and use a flag to indicate that static
3397     * calls don't count.  If we do this as part of copying the arguments
3398     * out we could avoiding loading the first arg twice.)
3399     *
3400     * for: invoke-direct, invoke-direct/range
3401     */
3402    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3403    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3404    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3405    FETCH(r1, 1)                        @ r1<- BBBB
3406    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3407    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3408    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3409    .if     (!1)
3410    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3411    .endif
3412    cmp     r0, #0                      @ already resolved?
3413    EXPORT_PC()                         @ must export for invoke
3414    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3415    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3416.LOP_INVOKE_DIRECT_RANGE_finish:
3417    cmp     r2, #0                      @ null "this" ref?
3418    bne     common_invokeMethodRange   @ no, continue on
3419    b       common_errNullObject        @ yes, throw exception
3420
3421
3422/* ------------------------------ */
3423    .balign 64
3424.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3425/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3426/* File: armv5te/OP_INVOKE_STATIC.S */
3427    /*
3428     * Handle a static method call.
3429     *
3430     * for: invoke-static, invoke-static/range
3431     */
3432    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3433    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3434    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3435    FETCH(r1, 1)                        @ r1<- BBBB
3436    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3437    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3438    cmp     r0, #0                      @ already resolved?
3439    EXPORT_PC()                         @ must export for invoke
3440    bne     common_invokeMethodRange @ yes, continue on
34410:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3442    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3443    mov     r2, #METHOD_STATIC          @ resolver method type
3444    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3445    cmp     r0, #0                      @ got null?
3446    bne     common_invokeMethodRange @ no, continue
3447    b       common_exceptionThrown      @ yes, handle exception
3448
3449
3450
3451/* ------------------------------ */
3452    .balign 64
3453.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3454/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3455/* File: armv5te/OP_INVOKE_INTERFACE.S */
3456    /*
3457     * Handle an interface method call.
3458     *
3459     * for: invoke-interface, invoke-interface/range
3460     */
3461    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3462    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3463    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3464    FETCH(r1, 1)                        @ r1<- BBBB
3465    .if     (!1)
3466    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3467    .endif
3468    EXPORT_PC()                         @ must export for invoke
3469    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3470    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3471    cmp     r0, #0                      @ null obj?
3472    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3473    beq     common_errNullObject        @ yes, fail
3474    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3475    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3476    cmp     r0, #0                      @ failed?
3477    beq     common_exceptionThrown      @ yes, handle exception
3478    b       common_invokeMethodRange @ jump to common handler
3479
3480
3481
3482/* ------------------------------ */
3483    .balign 64
3484.L_OP_UNUSED_79: /* 0x79 */
3485/* File: armv5te/OP_UNUSED_79.S */
3486/* File: armv5te/unused.S */
3487    bl      common_abort
3488
3489
3490
3491/* ------------------------------ */
3492    .balign 64
3493.L_OP_UNUSED_7A: /* 0x7a */
3494/* File: armv5te/OP_UNUSED_7A.S */
3495/* File: armv5te/unused.S */
3496    bl      common_abort
3497
3498
3499
3500/* ------------------------------ */
3501    .balign 64
3502.L_OP_NEG_INT: /* 0x7b */
3503/* File: armv6t2/OP_NEG_INT.S */
3504/* File: armv6t2/unop.S */
3505    /*
3506     * Generic 32-bit unary operation.  Provide an "instr" line that
3507     * specifies an instruction that performs "result = op r0".
3508     * This could be an ARM instruction or a function call.
3509     *
3510     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3511     *      int-to-byte, int-to-char, int-to-short
3512     */
3513    /* unop vA, vB */
3514    mov     r3, rINST, lsr #12          @ r3<- B
3515    ubfx    r9, rINST, #8, #4           @ r9<- A
3516    GET_VREG(r0, r3)                    @ r0<- vB
3517                               @ optional op; may set condition codes
3518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3519    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3521    SET_VREG(r0, r9)                    @ vAA<- r0
3522    GOTO_OPCODE(ip)                     @ jump to next instruction
3523    /* 8-9 instructions */
3524
3525
3526/* ------------------------------ */
3527    .balign 64
3528.L_OP_NOT_INT: /* 0x7c */
3529/* File: armv6t2/OP_NOT_INT.S */
3530/* File: armv6t2/unop.S */
3531    /*
3532     * Generic 32-bit unary operation.  Provide an "instr" line that
3533     * specifies an instruction that performs "result = op r0".
3534     * This could be an ARM instruction or a function call.
3535     *
3536     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3537     *      int-to-byte, int-to-char, int-to-short
3538     */
3539    /* unop vA, vB */
3540    mov     r3, rINST, lsr #12          @ r3<- B
3541    ubfx    r9, rINST, #8, #4           @ r9<- A
3542    GET_VREG(r0, r3)                    @ r0<- vB
3543                               @ optional op; may set condition codes
3544    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3545    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3547    SET_VREG(r0, r9)                    @ vAA<- r0
3548    GOTO_OPCODE(ip)                     @ jump to next instruction
3549    /* 8-9 instructions */
3550
3551
3552/* ------------------------------ */
3553    .balign 64
3554.L_OP_NEG_LONG: /* 0x7d */
3555/* File: armv6t2/OP_NEG_LONG.S */
3556/* File: armv6t2/unopWide.S */
3557    /*
3558     * Generic 64-bit unary operation.  Provide an "instr" line that
3559     * specifies an instruction that performs "result = op r0/r1".
3560     * This could be an ARM instruction or a function call.
3561     *
3562     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3563     */
3564    /* unop vA, vB */
3565    mov     r3, rINST, lsr #12          @ r3<- B
3566    ubfx    r9, rINST, #8, #4           @ r9<- A
3567    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3568    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3569    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3570    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3571    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3572    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3574    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3575    GOTO_OPCODE(ip)                     @ jump to next instruction
3576    /* 10-11 instructions */
3577
3578
3579
3580/* ------------------------------ */
3581    .balign 64
3582.L_OP_NOT_LONG: /* 0x7e */
3583/* File: armv6t2/OP_NOT_LONG.S */
3584/* File: armv6t2/unopWide.S */
3585    /*
3586     * Generic 64-bit unary operation.  Provide an "instr" line that
3587     * specifies an instruction that performs "result = op r0/r1".
3588     * This could be an ARM instruction or a function call.
3589     *
3590     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3591     */
3592    /* unop vA, vB */
3593    mov     r3, rINST, lsr #12          @ r3<- B
3594    ubfx    r9, rINST, #8, #4           @ r9<- A
3595    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3596    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3597    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3598    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3599    mvn     r0, r0                           @ optional op; may set condition codes
3600    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3601    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3602    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3603    GOTO_OPCODE(ip)                     @ jump to next instruction
3604    /* 10-11 instructions */
3605
3606
3607
3608/* ------------------------------ */
3609    .balign 64
3610.L_OP_NEG_FLOAT: /* 0x7f */
3611/* File: armv6t2/OP_NEG_FLOAT.S */
3612/* File: armv6t2/unop.S */
3613    /*
3614     * Generic 32-bit unary operation.  Provide an "instr" line that
3615     * specifies an instruction that performs "result = op r0".
3616     * This could be an ARM instruction or a function call.
3617     *
3618     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3619     *      int-to-byte, int-to-char, int-to-short
3620     */
3621    /* unop vA, vB */
3622    mov     r3, rINST, lsr #12          @ r3<- B
3623    ubfx    r9, rINST, #8, #4           @ r9<- A
3624    GET_VREG(r0, r3)                    @ r0<- vB
3625                               @ optional op; may set condition codes
3626    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3627    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3628    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3629    SET_VREG(r0, r9)                    @ vAA<- r0
3630    GOTO_OPCODE(ip)                     @ jump to next instruction
3631    /* 8-9 instructions */
3632
3633
3634/* ------------------------------ */
3635    .balign 64
3636.L_OP_NEG_DOUBLE: /* 0x80 */
3637/* File: armv6t2/OP_NEG_DOUBLE.S */
3638/* File: armv6t2/unopWide.S */
3639    /*
3640     * Generic 64-bit unary operation.  Provide an "instr" line that
3641     * specifies an instruction that performs "result = op r0/r1".
3642     * This could be an ARM instruction or a function call.
3643     *
3644     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3645     */
3646    /* unop vA, vB */
3647    mov     r3, rINST, lsr #12          @ r3<- B
3648    ubfx    r9, rINST, #8, #4           @ r9<- A
3649    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3650    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3651    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3652    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3653                               @ optional op; may set condition codes
3654    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3655    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3656    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3657    GOTO_OPCODE(ip)                     @ jump to next instruction
3658    /* 10-11 instructions */
3659
3660
3661
3662/* ------------------------------ */
3663    .balign 64
3664.L_OP_INT_TO_LONG: /* 0x81 */
3665/* File: armv6t2/OP_INT_TO_LONG.S */
3666/* File: armv6t2/unopWider.S */
3667    /*
3668     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3669     * that specifies an instruction that performs "result = op r0", where
3670     * "result" is a 64-bit quantity in r0/r1.
3671     *
3672     * For: int-to-long, int-to-double, float-to-long, float-to-double
3673     */
3674    /* unop vA, vB */
3675    mov     r3, rINST, lsr #12          @ r3<- B
3676    ubfx    r9, rINST, #8, #4           @ r9<- A
3677    GET_VREG(r0, r3)                    @ r0<- vB
3678    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3679                               @ optional op; may set condition codes
3680    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3681    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3682    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3683    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3684    GOTO_OPCODE(ip)                     @ jump to next instruction
3685    /* 9-10 instructions */
3686
3687
3688/* ------------------------------ */
3689    .balign 64
3690.L_OP_INT_TO_FLOAT: /* 0x82 */
3691/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3692/* File: arm-vfp/funop.S */
3693    /*
3694     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3695     * line that specifies an instruction that performs "s1 = op s0".
3696     *
3697     * for: int-to-float, float-to-int
3698     */
3699    /* unop vA, vB */
3700    mov     r3, rINST, lsr #12          @ r3<- B
3701    mov     r9, rINST, lsr #8           @ r9<- A+
3702    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3703    flds    s0, [r3]                    @ s0<- vB
3704    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3705    and     r9, r9, #15                 @ r9<- A
3706    fsitos  s1, s0                              @ s1<- op
3707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3708    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3709    fsts    s1, [r9]                    @ vA<- s1
3710    GOTO_OPCODE(ip)                     @ jump to next instruction
3711
3712
3713/* ------------------------------ */
3714    .balign 64
3715.L_OP_INT_TO_DOUBLE: /* 0x83 */
3716/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3717/* File: arm-vfp/funopWider.S */
3718    /*
3719     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3720     * "instr" line that specifies an instruction that performs "d0 = op s0".
3721     *
3722     * For: int-to-double, float-to-double
3723     */
3724    /* unop vA, vB */
3725    mov     r3, rINST, lsr #12          @ r3<- B
3726    mov     r9, rINST, lsr #8           @ r9<- A+
3727    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3728    flds    s0, [r3]                    @ s0<- vB
3729    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3730    and     r9, r9, #15                 @ r9<- A
3731    fsitod  d0, s0                              @ d0<- op
3732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3733    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3734    fstd    d0, [r9]                    @ vA<- d0
3735    GOTO_OPCODE(ip)                     @ jump to next instruction
3736
3737
3738/* ------------------------------ */
3739    .balign 64
3740.L_OP_LONG_TO_INT: /* 0x84 */
3741/* File: armv5te/OP_LONG_TO_INT.S */
3742/* we ignore the high word, making this equivalent to a 32-bit reg move */
3743/* File: armv5te/OP_MOVE.S */
3744    /* for move, move-object, long-to-int */
3745    /* op vA, vB */
3746    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3747    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3748    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3749    GET_VREG(r2, r1)                    @ r2<- fp[B]
3750    and     r0, r0, #15
3751    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3752    SET_VREG(r2, r0)                    @ fp[A]<- r2
3753    GOTO_OPCODE(ip)                     @ execute next instruction
3754
3755
3756
3757/* ------------------------------ */
3758    .balign 64
3759.L_OP_LONG_TO_FLOAT: /* 0x85 */
3760/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3761/* File: armv6t2/unopNarrower.S */
3762    /*
3763     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3764     * that specifies an instruction that performs "result = op r0/r1", where
3765     * "result" is a 32-bit quantity in r0.
3766     *
3767     * For: long-to-float, double-to-int, double-to-float
3768     *
3769     * (This would work for long-to-int, but that instruction is actually
3770     * an exact match for OP_MOVE.)
3771     */
3772    /* unop vA, vB */
3773    mov     r3, rINST, lsr #12          @ r3<- B
3774    ubfx    r9, rINST, #8, #4           @ r9<- A
3775    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3776    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3777    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3778                               @ optional op; may set condition codes
3779    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3781    SET_VREG(r0, r9)                    @ vA<- r0
3782    GOTO_OPCODE(ip)                     @ jump to next instruction
3783    /* 9-10 instructions */
3784
3785
3786/* ------------------------------ */
3787    .balign 64
3788.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3789/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3790/* File: armv6t2/unopWide.S */
3791    /*
3792     * Generic 64-bit unary operation.  Provide an "instr" line that
3793     * specifies an instruction that performs "result = op r0/r1".
3794     * This could be an ARM instruction or a function call.
3795     *
3796     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3797     */
3798    /* unop vA, vB */
3799    mov     r3, rINST, lsr #12          @ r3<- B
3800    ubfx    r9, rINST, #8, #4           @ r9<- A
3801    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3802    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3803    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3804    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3805                               @ optional op; may set condition codes
3806    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3808    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3809    GOTO_OPCODE(ip)                     @ jump to next instruction
3810    /* 10-11 instructions */
3811
3812
3813
3814/* ------------------------------ */
3815    .balign 64
3816.L_OP_FLOAT_TO_INT: /* 0x87 */
3817/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3818/* File: arm-vfp/funop.S */
3819    /*
3820     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3821     * line that specifies an instruction that performs "s1 = op s0".
3822     *
3823     * for: int-to-float, float-to-int
3824     */
3825    /* unop vA, vB */
3826    mov     r3, rINST, lsr #12          @ r3<- B
3827    mov     r9, rINST, lsr #8           @ r9<- A+
3828    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3829    flds    s0, [r3]                    @ s0<- vB
3830    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3831    and     r9, r9, #15                 @ r9<- A
3832    ftosizs s1, s0                              @ s1<- op
3833    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3834    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3835    fsts    s1, [r9]                    @ vA<- s1
3836    GOTO_OPCODE(ip)                     @ jump to next instruction
3837
3838
3839/* ------------------------------ */
3840    .balign 64
3841.L_OP_FLOAT_TO_LONG: /* 0x88 */
3842/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3843@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3844/* File: armv6t2/unopWider.S */
3845    /*
3846     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3847     * that specifies an instruction that performs "result = op r0", where
3848     * "result" is a 64-bit quantity in r0/r1.
3849     *
3850     * For: int-to-long, int-to-double, float-to-long, float-to-double
3851     */
3852    /* unop vA, vB */
3853    mov     r3, rINST, lsr #12          @ r3<- B
3854    ubfx    r9, rINST, #8, #4           @ r9<- A
3855    GET_VREG(r0, r3)                    @ r0<- vB
3856    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3857                               @ optional op; may set condition codes
3858    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3859    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3861    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3862    GOTO_OPCODE(ip)                     @ jump to next instruction
3863    /* 9-10 instructions */
3864
3865
3866
3867/* ------------------------------ */
3868    .balign 64
3869.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3870/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3871/* File: arm-vfp/funopWider.S */
3872    /*
3873     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3874     * "instr" line that specifies an instruction that performs "d0 = op s0".
3875     *
3876     * For: int-to-double, float-to-double
3877     */
3878    /* unop vA, vB */
3879    mov     r3, rINST, lsr #12          @ r3<- B
3880    mov     r9, rINST, lsr #8           @ r9<- A+
3881    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3882    flds    s0, [r3]                    @ s0<- vB
3883    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3884    and     r9, r9, #15                 @ r9<- A
3885    fcvtds  d0, s0                              @ d0<- op
3886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3887    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3888    fstd    d0, [r9]                    @ vA<- d0
3889    GOTO_OPCODE(ip)                     @ jump to next instruction
3890
3891
3892/* ------------------------------ */
3893    .balign 64
3894.L_OP_DOUBLE_TO_INT: /* 0x8a */
3895/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3896/* File: arm-vfp/funopNarrower.S */
3897    /*
3898     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3899     * "instr" line that specifies an instruction that performs "s0 = op d0".
3900     *
3901     * For: double-to-int, double-to-float
3902     */
3903    /* unop vA, vB */
3904    mov     r3, rINST, lsr #12          @ r3<- B
3905    mov     r9, rINST, lsr #8           @ r9<- A+
3906    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3907    fldd    d0, [r3]                    @ d0<- vB
3908    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3909    and     r9, r9, #15                 @ r9<- A
3910    ftosizd  s0, d0                              @ s0<- op
3911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3912    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3913    fsts    s0, [r9]                    @ vA<- s0
3914    GOTO_OPCODE(ip)                     @ jump to next instruction
3915
3916
3917/* ------------------------------ */
3918    .balign 64
3919.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3920/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3921@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3922/* File: armv6t2/unopWide.S */
3923    /*
3924     * Generic 64-bit unary operation.  Provide an "instr" line that
3925     * specifies an instruction that performs "result = op r0/r1".
3926     * This could be an ARM instruction or a function call.
3927     *
3928     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3929     */
3930    /* unop vA, vB */
3931    mov     r3, rINST, lsr #12          @ r3<- B
3932    ubfx    r9, rINST, #8, #4           @ r9<- A
3933    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3934    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3935    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3936    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3937                               @ optional op; may set condition codes
3938    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3940    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3941    GOTO_OPCODE(ip)                     @ jump to next instruction
3942    /* 10-11 instructions */
3943
3944
3945
3946
3947/* ------------------------------ */
3948    .balign 64
3949.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3950/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3951/* File: arm-vfp/funopNarrower.S */
3952    /*
3953     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3954     * "instr" line that specifies an instruction that performs "s0 = op d0".
3955     *
3956     * For: double-to-int, double-to-float
3957     */
3958    /* unop vA, vB */
3959    mov     r3, rINST, lsr #12          @ r3<- B
3960    mov     r9, rINST, lsr #8           @ r9<- A+
3961    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3962    fldd    d0, [r3]                    @ d0<- vB
3963    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3964    and     r9, r9, #15                 @ r9<- A
3965    fcvtsd  s0, d0                              @ s0<- op
3966    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3967    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3968    fsts    s0, [r9]                    @ vA<- s0
3969    GOTO_OPCODE(ip)                     @ jump to next instruction
3970
3971
3972/* ------------------------------ */
3973    .balign 64
3974.L_OP_INT_TO_BYTE: /* 0x8d */
3975/* File: armv6t2/OP_INT_TO_BYTE.S */
3976/* File: armv6t2/unop.S */
3977    /*
3978     * Generic 32-bit unary operation.  Provide an "instr" line that
3979     * specifies an instruction that performs "result = op r0".
3980     * This could be an ARM instruction or a function call.
3981     *
3982     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3983     *      int-to-byte, int-to-char, int-to-short
3984     */
3985    /* unop vA, vB */
3986    mov     r3, rINST, lsr #12          @ r3<- B
3987    ubfx    r9, rINST, #8, #4           @ r9<- A
3988    GET_VREG(r0, r3)                    @ r0<- vB
3989                               @ optional op; may set condition codes
3990    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3991    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3993    SET_VREG(r0, r9)                    @ vAA<- r0
3994    GOTO_OPCODE(ip)                     @ jump to next instruction
3995    /* 8-9 instructions */
3996
3997
3998/* ------------------------------ */
3999    .balign 64
4000.L_OP_INT_TO_CHAR: /* 0x8e */
4001/* File: armv6t2/OP_INT_TO_CHAR.S */
4002/* File: armv6t2/unop.S */
4003    /*
4004     * Generic 32-bit unary operation.  Provide an "instr" line that
4005     * specifies an instruction that performs "result = op r0".
4006     * This could be an ARM instruction or a function call.
4007     *
4008     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4009     *      int-to-byte, int-to-char, int-to-short
4010     */
4011    /* unop vA, vB */
4012    mov     r3, rINST, lsr #12          @ r3<- B
4013    ubfx    r9, rINST, #8, #4           @ r9<- A
4014    GET_VREG(r0, r3)                    @ r0<- vB
4015                               @ optional op; may set condition codes
4016    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4017    uxth    r0, r0                              @ r0<- op, r0-r3 changed
4018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4019    SET_VREG(r0, r9)                    @ vAA<- r0
4020    GOTO_OPCODE(ip)                     @ jump to next instruction
4021    /* 8-9 instructions */
4022
4023
4024/* ------------------------------ */
4025    .balign 64
4026.L_OP_INT_TO_SHORT: /* 0x8f */
4027/* File: armv6t2/OP_INT_TO_SHORT.S */
4028/* File: armv6t2/unop.S */
4029    /*
4030     * Generic 32-bit unary operation.  Provide an "instr" line that
4031     * specifies an instruction that performs "result = op r0".
4032     * This could be an ARM instruction or a function call.
4033     *
4034     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4035     *      int-to-byte, int-to-char, int-to-short
4036     */
4037    /* unop vA, vB */
4038    mov     r3, rINST, lsr #12          @ r3<- B
4039    ubfx    r9, rINST, #8, #4           @ r9<- A
4040    GET_VREG(r0, r3)                    @ r0<- vB
4041                               @ optional op; may set condition codes
4042    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4043    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4044    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4045    SET_VREG(r0, r9)                    @ vAA<- r0
4046    GOTO_OPCODE(ip)                     @ jump to next instruction
4047    /* 8-9 instructions */
4048
4049
4050/* ------------------------------ */
4051    .balign 64
4052.L_OP_ADD_INT: /* 0x90 */
4053/* File: armv5te/OP_ADD_INT.S */
4054/* File: armv5te/binop.S */
4055    /*
4056     * Generic 32-bit binary operation.  Provide an "instr" line that
4057     * specifies an instruction that performs "result = r0 op r1".
4058     * This could be an ARM instruction or a function call.  (If the result
4059     * comes back in a register other than r0, you can override "result".)
4060     *
4061     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4062     * vCC (r1).  Useful for integer division and modulus.  Note that we
4063     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4064     * handles it correctly.
4065     *
4066     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4067     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4068     *      mul-float, div-float, rem-float
4069     */
4070    /* binop vAA, vBB, vCC */
4071    FETCH(r0, 1)                        @ r0<- CCBB
4072    mov     r9, rINST, lsr #8           @ r9<- AA
4073    mov     r3, r0, lsr #8              @ r3<- CC
4074    and     r2, r0, #255                @ r2<- BB
4075    GET_VREG(r1, r3)                    @ r1<- vCC
4076    GET_VREG(r0, r2)                    @ r0<- vBB
4077    .if 0
4078    cmp     r1, #0                      @ is second operand zero?
4079    beq     common_errDivideByZero
4080    .endif
4081
4082    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4083                               @ optional op; may set condition codes
4084    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4085    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4086    SET_VREG(r0, r9)               @ vAA<- r0
4087    GOTO_OPCODE(ip)                     @ jump to next instruction
4088    /* 11-14 instructions */
4089
4090
4091
4092/* ------------------------------ */
4093    .balign 64
4094.L_OP_SUB_INT: /* 0x91 */
4095/* File: armv5te/OP_SUB_INT.S */
4096/* File: armv5te/binop.S */
4097    /*
4098     * Generic 32-bit binary operation.  Provide an "instr" line that
4099     * specifies an instruction that performs "result = r0 op r1".
4100     * This could be an ARM instruction or a function call.  (If the result
4101     * comes back in a register other than r0, you can override "result".)
4102     *
4103     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4104     * vCC (r1).  Useful for integer division and modulus.  Note that we
4105     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4106     * handles it correctly.
4107     *
4108     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4109     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4110     *      mul-float, div-float, rem-float
4111     */
4112    /* binop vAA, vBB, vCC */
4113    FETCH(r0, 1)                        @ r0<- CCBB
4114    mov     r9, rINST, lsr #8           @ r9<- AA
4115    mov     r3, r0, lsr #8              @ r3<- CC
4116    and     r2, r0, #255                @ r2<- BB
4117    GET_VREG(r1, r3)                    @ r1<- vCC
4118    GET_VREG(r0, r2)                    @ r0<- vBB
4119    .if 0
4120    cmp     r1, #0                      @ is second operand zero?
4121    beq     common_errDivideByZero
4122    .endif
4123
4124    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4125                               @ optional op; may set condition codes
4126    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4127    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4128    SET_VREG(r0, r9)               @ vAA<- r0
4129    GOTO_OPCODE(ip)                     @ jump to next instruction
4130    /* 11-14 instructions */
4131
4132
4133
4134/* ------------------------------ */
4135    .balign 64
4136.L_OP_MUL_INT: /* 0x92 */
4137/* File: armv5te/OP_MUL_INT.S */
4138/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4139/* File: armv5te/binop.S */
4140    /*
4141     * Generic 32-bit binary operation.  Provide an "instr" line that
4142     * specifies an instruction that performs "result = r0 op r1".
4143     * This could be an ARM instruction or a function call.  (If the result
4144     * comes back in a register other than r0, you can override "result".)
4145     *
4146     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4147     * vCC (r1).  Useful for integer division and modulus.  Note that we
4148     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4149     * handles it correctly.
4150     *
4151     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4152     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4153     *      mul-float, div-float, rem-float
4154     */
4155    /* binop vAA, vBB, vCC */
4156    FETCH(r0, 1)                        @ r0<- CCBB
4157    mov     r9, rINST, lsr #8           @ r9<- AA
4158    mov     r3, r0, lsr #8              @ r3<- CC
4159    and     r2, r0, #255                @ r2<- BB
4160    GET_VREG(r1, r3)                    @ r1<- vCC
4161    GET_VREG(r0, r2)                    @ r0<- vBB
4162    .if 0
4163    cmp     r1, #0                      @ is second operand zero?
4164    beq     common_errDivideByZero
4165    .endif
4166
4167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4168                               @ optional op; may set condition codes
4169    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4171    SET_VREG(r0, r9)               @ vAA<- r0
4172    GOTO_OPCODE(ip)                     @ jump to next instruction
4173    /* 11-14 instructions */
4174
4175
4176
4177/* ------------------------------ */
4178    .balign 64
4179.L_OP_DIV_INT: /* 0x93 */
4180/* File: armv5te/OP_DIV_INT.S */
4181/* File: armv5te/binop.S */
4182    /*
4183     * Generic 32-bit binary operation.  Provide an "instr" line that
4184     * specifies an instruction that performs "result = r0 op r1".
4185     * This could be an ARM instruction or a function call.  (If the result
4186     * comes back in a register other than r0, you can override "result".)
4187     *
4188     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4189     * vCC (r1).  Useful for integer division and modulus.  Note that we
4190     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4191     * handles it correctly.
4192     *
4193     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4194     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4195     *      mul-float, div-float, rem-float
4196     */
4197    /* binop vAA, vBB, vCC */
4198    FETCH(r0, 1)                        @ r0<- CCBB
4199    mov     r9, rINST, lsr #8           @ r9<- AA
4200    mov     r3, r0, lsr #8              @ r3<- CC
4201    and     r2, r0, #255                @ r2<- BB
4202    GET_VREG(r1, r3)                    @ r1<- vCC
4203    GET_VREG(r0, r2)                    @ r0<- vBB
4204    .if 1
4205    cmp     r1, #0                      @ is second operand zero?
4206    beq     common_errDivideByZero
4207    .endif
4208
4209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4210                               @ optional op; may set condition codes
4211    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4213    SET_VREG(r0, r9)               @ vAA<- r0
4214    GOTO_OPCODE(ip)                     @ jump to next instruction
4215    /* 11-14 instructions */
4216
4217
4218
4219/* ------------------------------ */
4220    .balign 64
4221.L_OP_REM_INT: /* 0x94 */
4222/* File: armv5te/OP_REM_INT.S */
4223/* idivmod returns quotient in r0 and remainder in r1 */
4224/* File: armv5te/binop.S */
4225    /*
4226     * Generic 32-bit binary operation.  Provide an "instr" line that
4227     * specifies an instruction that performs "result = r0 op r1".
4228     * This could be an ARM instruction or a function call.  (If the result
4229     * comes back in a register other than r0, you can override "result".)
4230     *
4231     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4232     * vCC (r1).  Useful for integer division and modulus.  Note that we
4233     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4234     * handles it correctly.
4235     *
4236     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4237     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4238     *      mul-float, div-float, rem-float
4239     */
4240    /* binop vAA, vBB, vCC */
4241    FETCH(r0, 1)                        @ r0<- CCBB
4242    mov     r9, rINST, lsr #8           @ r9<- AA
4243    mov     r3, r0, lsr #8              @ r3<- CC
4244    and     r2, r0, #255                @ r2<- BB
4245    GET_VREG(r1, r3)                    @ r1<- vCC
4246    GET_VREG(r0, r2)                    @ r0<- vBB
4247    .if 1
4248    cmp     r1, #0                      @ is second operand zero?
4249    beq     common_errDivideByZero
4250    .endif
4251
4252    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4253                               @ optional op; may set condition codes
4254    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4256    SET_VREG(r1, r9)               @ vAA<- r1
4257    GOTO_OPCODE(ip)                     @ jump to next instruction
4258    /* 11-14 instructions */
4259
4260
4261
4262/* ------------------------------ */
4263    .balign 64
4264.L_OP_AND_INT: /* 0x95 */
4265/* File: armv5te/OP_AND_INT.S */
4266/* File: armv5te/binop.S */
4267    /*
4268     * Generic 32-bit binary operation.  Provide an "instr" line that
4269     * specifies an instruction that performs "result = r0 op r1".
4270     * This could be an ARM instruction or a function call.  (If the result
4271     * comes back in a register other than r0, you can override "result".)
4272     *
4273     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4274     * vCC (r1).  Useful for integer division and modulus.  Note that we
4275     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4276     * handles it correctly.
4277     *
4278     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4279     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4280     *      mul-float, div-float, rem-float
4281     */
4282    /* binop vAA, vBB, vCC */
4283    FETCH(r0, 1)                        @ r0<- CCBB
4284    mov     r9, rINST, lsr #8           @ r9<- AA
4285    mov     r3, r0, lsr #8              @ r3<- CC
4286    and     r2, r0, #255                @ r2<- BB
4287    GET_VREG(r1, r3)                    @ r1<- vCC
4288    GET_VREG(r0, r2)                    @ r0<- vBB
4289    .if 0
4290    cmp     r1, #0                      @ is second operand zero?
4291    beq     common_errDivideByZero
4292    .endif
4293
4294    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4295                               @ optional op; may set condition codes
4296    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4298    SET_VREG(r0, r9)               @ vAA<- r0
4299    GOTO_OPCODE(ip)                     @ jump to next instruction
4300    /* 11-14 instructions */
4301
4302
4303
4304/* ------------------------------ */
4305    .balign 64
4306.L_OP_OR_INT: /* 0x96 */
4307/* File: armv5te/OP_OR_INT.S */
4308/* File: armv5te/binop.S */
4309    /*
4310     * Generic 32-bit binary operation.  Provide an "instr" line that
4311     * specifies an instruction that performs "result = r0 op r1".
4312     * This could be an ARM instruction or a function call.  (If the result
4313     * comes back in a register other than r0, you can override "result".)
4314     *
4315     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4316     * vCC (r1).  Useful for integer division and modulus.  Note that we
4317     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4318     * handles it correctly.
4319     *
4320     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4321     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4322     *      mul-float, div-float, rem-float
4323     */
4324    /* binop vAA, vBB, vCC */
4325    FETCH(r0, 1)                        @ r0<- CCBB
4326    mov     r9, rINST, lsr #8           @ r9<- AA
4327    mov     r3, r0, lsr #8              @ r3<- CC
4328    and     r2, r0, #255                @ r2<- BB
4329    GET_VREG(r1, r3)                    @ r1<- vCC
4330    GET_VREG(r0, r2)                    @ r0<- vBB
4331    .if 0
4332    cmp     r1, #0                      @ is second operand zero?
4333    beq     common_errDivideByZero
4334    .endif
4335
4336    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4337                               @ optional op; may set condition codes
4338    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4340    SET_VREG(r0, r9)               @ vAA<- r0
4341    GOTO_OPCODE(ip)                     @ jump to next instruction
4342    /* 11-14 instructions */
4343
4344
4345
4346/* ------------------------------ */
4347    .balign 64
4348.L_OP_XOR_INT: /* 0x97 */
4349/* File: armv5te/OP_XOR_INT.S */
4350/* File: armv5te/binop.S */
4351    /*
4352     * Generic 32-bit binary operation.  Provide an "instr" line that
4353     * specifies an instruction that performs "result = r0 op r1".
4354     * This could be an ARM instruction or a function call.  (If the result
4355     * comes back in a register other than r0, you can override "result".)
4356     *
4357     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4358     * vCC (r1).  Useful for integer division and modulus.  Note that we
4359     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4360     * handles it correctly.
4361     *
4362     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4363     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4364     *      mul-float, div-float, rem-float
4365     */
4366    /* binop vAA, vBB, vCC */
4367    FETCH(r0, 1)                        @ r0<- CCBB
4368    mov     r9, rINST, lsr #8           @ r9<- AA
4369    mov     r3, r0, lsr #8              @ r3<- CC
4370    and     r2, r0, #255                @ r2<- BB
4371    GET_VREG(r1, r3)                    @ r1<- vCC
4372    GET_VREG(r0, r2)                    @ r0<- vBB
4373    .if 0
4374    cmp     r1, #0                      @ is second operand zero?
4375    beq     common_errDivideByZero
4376    .endif
4377
4378    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4379                               @ optional op; may set condition codes
4380    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4381    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4382    SET_VREG(r0, r9)               @ vAA<- r0
4383    GOTO_OPCODE(ip)                     @ jump to next instruction
4384    /* 11-14 instructions */
4385
4386
4387
4388/* ------------------------------ */
4389    .balign 64
4390.L_OP_SHL_INT: /* 0x98 */
4391/* File: armv5te/OP_SHL_INT.S */
4392/* File: armv5te/binop.S */
4393    /*
4394     * Generic 32-bit binary operation.  Provide an "instr" line that
4395     * specifies an instruction that performs "result = r0 op r1".
4396     * This could be an ARM instruction or a function call.  (If the result
4397     * comes back in a register other than r0, you can override "result".)
4398     *
4399     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4400     * vCC (r1).  Useful for integer division and modulus.  Note that we
4401     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4402     * handles it correctly.
4403     *
4404     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4405     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4406     *      mul-float, div-float, rem-float
4407     */
4408    /* binop vAA, vBB, vCC */
4409    FETCH(r0, 1)                        @ r0<- CCBB
4410    mov     r9, rINST, lsr #8           @ r9<- AA
4411    mov     r3, r0, lsr #8              @ r3<- CC
4412    and     r2, r0, #255                @ r2<- BB
4413    GET_VREG(r1, r3)                    @ r1<- vCC
4414    GET_VREG(r0, r2)                    @ r0<- vBB
4415    .if 0
4416    cmp     r1, #0                      @ is second operand zero?
4417    beq     common_errDivideByZero
4418    .endif
4419
4420    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4421    and     r1, r1, #31                           @ optional op; may set condition codes
4422    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4423    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4424    SET_VREG(r0, r9)               @ vAA<- r0
4425    GOTO_OPCODE(ip)                     @ jump to next instruction
4426    /* 11-14 instructions */
4427
4428
4429
4430/* ------------------------------ */
4431    .balign 64
4432.L_OP_SHR_INT: /* 0x99 */
4433/* File: armv5te/OP_SHR_INT.S */
4434/* File: armv5te/binop.S */
4435    /*
4436     * Generic 32-bit binary operation.  Provide an "instr" line that
4437     * specifies an instruction that performs "result = r0 op r1".
4438     * This could be an ARM instruction or a function call.  (If the result
4439     * comes back in a register other than r0, you can override "result".)
4440     *
4441     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4442     * vCC (r1).  Useful for integer division and modulus.  Note that we
4443     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4444     * handles it correctly.
4445     *
4446     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4447     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4448     *      mul-float, div-float, rem-float
4449     */
4450    /* binop vAA, vBB, vCC */
4451    FETCH(r0, 1)                        @ r0<- CCBB
4452    mov     r9, rINST, lsr #8           @ r9<- AA
4453    mov     r3, r0, lsr #8              @ r3<- CC
4454    and     r2, r0, #255                @ r2<- BB
4455    GET_VREG(r1, r3)                    @ r1<- vCC
4456    GET_VREG(r0, r2)                    @ r0<- vBB
4457    .if 0
4458    cmp     r1, #0                      @ is second operand zero?
4459    beq     common_errDivideByZero
4460    .endif
4461
4462    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4463    and     r1, r1, #31                           @ optional op; may set condition codes
4464    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4465    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4466    SET_VREG(r0, r9)               @ vAA<- r0
4467    GOTO_OPCODE(ip)                     @ jump to next instruction
4468    /* 11-14 instructions */
4469
4470
4471
4472/* ------------------------------ */
4473    .balign 64
4474.L_OP_USHR_INT: /* 0x9a */
4475/* File: armv5te/OP_USHR_INT.S */
4476/* File: armv5te/binop.S */
4477    /*
4478     * Generic 32-bit binary operation.  Provide an "instr" line that
4479     * specifies an instruction that performs "result = r0 op r1".
4480     * This could be an ARM instruction or a function call.  (If the result
4481     * comes back in a register other than r0, you can override "result".)
4482     *
4483     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4484     * vCC (r1).  Useful for integer division and modulus.  Note that we
4485     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4486     * handles it correctly.
4487     *
4488     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4489     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4490     *      mul-float, div-float, rem-float
4491     */
4492    /* binop vAA, vBB, vCC */
4493    FETCH(r0, 1)                        @ r0<- CCBB
4494    mov     r9, rINST, lsr #8           @ r9<- AA
4495    mov     r3, r0, lsr #8              @ r3<- CC
4496    and     r2, r0, #255                @ r2<- BB
4497    GET_VREG(r1, r3)                    @ r1<- vCC
4498    GET_VREG(r0, r2)                    @ r0<- vBB
4499    .if 0
4500    cmp     r1, #0                      @ is second operand zero?
4501    beq     common_errDivideByZero
4502    .endif
4503
4504    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4505    and     r1, r1, #31                           @ optional op; may set condition codes
4506    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4507    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4508    SET_VREG(r0, r9)               @ vAA<- r0
4509    GOTO_OPCODE(ip)                     @ jump to next instruction
4510    /* 11-14 instructions */
4511
4512
4513
4514/* ------------------------------ */
4515    .balign 64
4516.L_OP_ADD_LONG: /* 0x9b */
4517/* File: armv5te/OP_ADD_LONG.S */
4518/* File: armv5te/binopWide.S */
4519    /*
4520     * Generic 64-bit binary operation.  Provide an "instr" line that
4521     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4522     * This could be an ARM instruction or a function call.  (If the result
4523     * comes back in a register other than r0, you can override "result".)
4524     *
4525     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4526     * vCC (r1).  Useful for integer division and modulus.
4527     *
4528     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4529     *      xor-long, add-double, sub-double, mul-double, div-double,
4530     *      rem-double
4531     *
4532     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4533     */
4534    /* binop vAA, vBB, vCC */
4535    FETCH(r0, 1)                        @ r0<- CCBB
4536    mov     r9, rINST, lsr #8           @ r9<- AA
4537    and     r2, r0, #255                @ r2<- BB
4538    mov     r3, r0, lsr #8              @ r3<- CC
4539    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4540    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4541    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4542    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4543    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4544    .if 0
4545    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4546    beq     common_errDivideByZero
4547    .endif
4548    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4549
4550    adds    r0, r0, r2                           @ optional op; may set condition codes
4551    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4552    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4553    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4554    GOTO_OPCODE(ip)                     @ jump to next instruction
4555    /* 14-17 instructions */
4556
4557
4558
4559/* ------------------------------ */
4560    .balign 64
4561.L_OP_SUB_LONG: /* 0x9c */
4562/* File: armv5te/OP_SUB_LONG.S */
4563/* File: armv5te/binopWide.S */
4564    /*
4565     * Generic 64-bit binary operation.  Provide an "instr" line that
4566     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4567     * This could be an ARM instruction or a function call.  (If the result
4568     * comes back in a register other than r0, you can override "result".)
4569     *
4570     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4571     * vCC (r1).  Useful for integer division and modulus.
4572     *
4573     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4574     *      xor-long, add-double, sub-double, mul-double, div-double,
4575     *      rem-double
4576     *
4577     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4578     */
4579    /* binop vAA, vBB, vCC */
4580    FETCH(r0, 1)                        @ r0<- CCBB
4581    mov     r9, rINST, lsr #8           @ r9<- AA
4582    and     r2, r0, #255                @ r2<- BB
4583    mov     r3, r0, lsr #8              @ r3<- CC
4584    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4585    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4586    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4587    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4588    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4589    .if 0
4590    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4591    beq     common_errDivideByZero
4592    .endif
4593    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4594
4595    subs    r0, r0, r2                           @ optional op; may set condition codes
4596    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4597    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4598    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4599    GOTO_OPCODE(ip)                     @ jump to next instruction
4600    /* 14-17 instructions */
4601
4602
4603
4604/* ------------------------------ */
4605    .balign 64
4606.L_OP_MUL_LONG: /* 0x9d */
4607/* File: armv5te/OP_MUL_LONG.S */
4608    /*
4609     * Signed 64-bit integer multiply.
4610     *
4611     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4612     *        WX
4613     *      x YZ
4614     *  --------
4615     *     ZW ZX
4616     *  YW YX
4617     *
4618     * The low word of the result holds ZX, the high word holds
4619     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4620     * it doesn't fit in the low 64 bits.
4621     *
4622     * Unlike most ARM math operations, multiply instructions have
4623     * restrictions on using the same register more than once (Rd and Rm
4624     * cannot be the same).
4625     */
4626    /* mul-long vAA, vBB, vCC */
4627    FETCH(r0, 1)                        @ r0<- CCBB
4628    and     r2, r0, #255                @ r2<- BB
4629    mov     r3, r0, lsr #8              @ r3<- CC
4630    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4631    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4632    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4633    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4634    mul     ip, r2, r1                  @  ip<- ZxW
4635    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4636    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4637    mov     r0, rINST, lsr #8           @ r0<- AA
4638    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4639    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4640    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4641    b       .LOP_MUL_LONG_finish
4642
4643/* ------------------------------ */
4644    .balign 64
4645.L_OP_DIV_LONG: /* 0x9e */
4646/* File: armv5te/OP_DIV_LONG.S */
4647/* File: armv5te/binopWide.S */
4648    /*
4649     * Generic 64-bit binary operation.  Provide an "instr" line that
4650     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4651     * This could be an ARM instruction or a function call.  (If the result
4652     * comes back in a register other than r0, you can override "result".)
4653     *
4654     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4655     * vCC (r1).  Useful for integer division and modulus.
4656     *
4657     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4658     *      xor-long, add-double, sub-double, mul-double, div-double,
4659     *      rem-double
4660     *
4661     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4662     */
4663    /* binop vAA, vBB, vCC */
4664    FETCH(r0, 1)                        @ r0<- CCBB
4665    mov     r9, rINST, lsr #8           @ r9<- AA
4666    and     r2, r0, #255                @ r2<- BB
4667    mov     r3, r0, lsr #8              @ r3<- CC
4668    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4669    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4670    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4671    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4672    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4673    .if 1
4674    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4675    beq     common_errDivideByZero
4676    .endif
4677    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4678
4679                               @ optional op; may set condition codes
4680    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4681    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4682    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4683    GOTO_OPCODE(ip)                     @ jump to next instruction
4684    /* 14-17 instructions */
4685
4686
4687
4688/* ------------------------------ */
4689    .balign 64
4690.L_OP_REM_LONG: /* 0x9f */
4691/* File: armv5te/OP_REM_LONG.S */
4692/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4693/* File: armv5te/binopWide.S */
4694    /*
4695     * Generic 64-bit binary operation.  Provide an "instr" line that
4696     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4697     * This could be an ARM instruction or a function call.  (If the result
4698     * comes back in a register other than r0, you can override "result".)
4699     *
4700     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4701     * vCC (r1).  Useful for integer division and modulus.
4702     *
4703     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4704     *      xor-long, add-double, sub-double, mul-double, div-double,
4705     *      rem-double
4706     *
4707     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4708     */
4709    /* binop vAA, vBB, vCC */
4710    FETCH(r0, 1)                        @ r0<- CCBB
4711    mov     r9, rINST, lsr #8           @ r9<- AA
4712    and     r2, r0, #255                @ r2<- BB
4713    mov     r3, r0, lsr #8              @ r3<- CC
4714    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4715    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4716    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4717    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4718    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4719    .if 1
4720    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4721    beq     common_errDivideByZero
4722    .endif
4723    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4724
4725                               @ optional op; may set condition codes
4726    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4728    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4729    GOTO_OPCODE(ip)                     @ jump to next instruction
4730    /* 14-17 instructions */
4731
4732
4733
4734/* ------------------------------ */
4735    .balign 64
4736.L_OP_AND_LONG: /* 0xa0 */
4737/* File: armv5te/OP_AND_LONG.S */
4738/* File: armv5te/binopWide.S */
4739    /*
4740     * Generic 64-bit binary operation.  Provide an "instr" line that
4741     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4742     * This could be an ARM instruction or a function call.  (If the result
4743     * comes back in a register other than r0, you can override "result".)
4744     *
4745     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4746     * vCC (r1).  Useful for integer division and modulus.
4747     *
4748     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4749     *      xor-long, add-double, sub-double, mul-double, div-double,
4750     *      rem-double
4751     *
4752     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4753     */
4754    /* binop vAA, vBB, vCC */
4755    FETCH(r0, 1)                        @ r0<- CCBB
4756    mov     r9, rINST, lsr #8           @ r9<- AA
4757    and     r2, r0, #255                @ r2<- BB
4758    mov     r3, r0, lsr #8              @ r3<- CC
4759    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4760    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4761    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4762    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4763    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4764    .if 0
4765    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4766    beq     common_errDivideByZero
4767    .endif
4768    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4769
4770    and     r0, r0, r2                           @ optional op; may set condition codes
4771    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4772    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4773    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4774    GOTO_OPCODE(ip)                     @ jump to next instruction
4775    /* 14-17 instructions */
4776
4777
4778
4779/* ------------------------------ */
4780    .balign 64
4781.L_OP_OR_LONG: /* 0xa1 */
4782/* File: armv5te/OP_OR_LONG.S */
4783/* File: armv5te/binopWide.S */
4784    /*
4785     * Generic 64-bit binary operation.  Provide an "instr" line that
4786     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4787     * This could be an ARM instruction or a function call.  (If the result
4788     * comes back in a register other than r0, you can override "result".)
4789     *
4790     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4791     * vCC (r1).  Useful for integer division and modulus.
4792     *
4793     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4794     *      xor-long, add-double, sub-double, mul-double, div-double,
4795     *      rem-double
4796     *
4797     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4798     */
4799    /* binop vAA, vBB, vCC */
4800    FETCH(r0, 1)                        @ r0<- CCBB
4801    mov     r9, rINST, lsr #8           @ r9<- AA
4802    and     r2, r0, #255                @ r2<- BB
4803    mov     r3, r0, lsr #8              @ r3<- CC
4804    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4805    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4806    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4807    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4808    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4809    .if 0
4810    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4811    beq     common_errDivideByZero
4812    .endif
4813    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4814
4815    orr     r0, r0, r2                           @ optional op; may set condition codes
4816    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4817    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4818    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4819    GOTO_OPCODE(ip)                     @ jump to next instruction
4820    /* 14-17 instructions */
4821
4822
4823
4824/* ------------------------------ */
4825    .balign 64
4826.L_OP_XOR_LONG: /* 0xa2 */
4827/* File: armv5te/OP_XOR_LONG.S */
4828/* File: armv5te/binopWide.S */
4829    /*
4830     * Generic 64-bit binary operation.  Provide an "instr" line that
4831     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4832     * This could be an ARM instruction or a function call.  (If the result
4833     * comes back in a register other than r0, you can override "result".)
4834     *
4835     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4836     * vCC (r1).  Useful for integer division and modulus.
4837     *
4838     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4839     *      xor-long, add-double, sub-double, mul-double, div-double,
4840     *      rem-double
4841     *
4842     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4843     */
4844    /* binop vAA, vBB, vCC */
4845    FETCH(r0, 1)                        @ r0<- CCBB
4846    mov     r9, rINST, lsr #8           @ r9<- AA
4847    and     r2, r0, #255                @ r2<- BB
4848    mov     r3, r0, lsr #8              @ r3<- CC
4849    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4850    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4851    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4852    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4853    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4854    .if 0
4855    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4856    beq     common_errDivideByZero
4857    .endif
4858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4859
4860    eor     r0, r0, r2                           @ optional op; may set condition codes
4861    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4863    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4864    GOTO_OPCODE(ip)                     @ jump to next instruction
4865    /* 14-17 instructions */
4866
4867
4868
4869/* ------------------------------ */
4870    .balign 64
4871.L_OP_SHL_LONG: /* 0xa3 */
4872/* File: armv5te/OP_SHL_LONG.S */
4873    /*
4874     * Long integer shift.  This is different from the generic 32/64-bit
4875     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4876     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4877     * 6 bits of the shift distance.
4878     */
4879    /* shl-long vAA, vBB, vCC */
4880    FETCH(r0, 1)                        @ r0<- CCBB
4881    mov     r9, rINST, lsr #8           @ r9<- AA
4882    and     r3, r0, #255                @ r3<- BB
4883    mov     r0, r0, lsr #8              @ r0<- CC
4884    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4885    GET_VREG(r2, r0)                    @ r2<- vCC
4886    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4887    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4888    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4889
4890    mov     r1, r1, asl r2              @  r1<- r1 << r2
4891    rsb     r3, r2, #32                 @  r3<- 32 - r2
4892    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4893    subs    ip, r2, #32                 @  ip<- r2 - 32
4894    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4895    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4896    b       .LOP_SHL_LONG_finish
4897
4898/* ------------------------------ */
4899    .balign 64
4900.L_OP_SHR_LONG: /* 0xa4 */
4901/* File: armv5te/OP_SHR_LONG.S */
4902    /*
4903     * Long integer shift.  This is different from the generic 32/64-bit
4904     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4905     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4906     * 6 bits of the shift distance.
4907     */
4908    /* shr-long vAA, vBB, vCC */
4909    FETCH(r0, 1)                        @ r0<- CCBB
4910    mov     r9, rINST, lsr #8           @ r9<- AA
4911    and     r3, r0, #255                @ r3<- BB
4912    mov     r0, r0, lsr #8              @ r0<- CC
4913    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4914    GET_VREG(r2, r0)                    @ r2<- vCC
4915    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4916    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4917    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4918
4919    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4920    rsb     r3, r2, #32                 @  r3<- 32 - r2
4921    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4922    subs    ip, r2, #32                 @  ip<- r2 - 32
4923    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4924    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4925    b       .LOP_SHR_LONG_finish
4926
4927/* ------------------------------ */
4928    .balign 64
4929.L_OP_USHR_LONG: /* 0xa5 */
4930/* File: armv5te/OP_USHR_LONG.S */
4931    /*
4932     * Long integer shift.  This is different from the generic 32/64-bit
4933     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4934     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4935     * 6 bits of the shift distance.
4936     */
4937    /* ushr-long vAA, vBB, vCC */
4938    FETCH(r0, 1)                        @ r0<- CCBB
4939    mov     r9, rINST, lsr #8           @ r9<- AA
4940    and     r3, r0, #255                @ r3<- BB
4941    mov     r0, r0, lsr #8              @ r0<- CC
4942    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4943    GET_VREG(r2, r0)                    @ r2<- vCC
4944    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4945    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4946    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4947
4948    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4949    rsb     r3, r2, #32                 @  r3<- 32 - r2
4950    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4951    subs    ip, r2, #32                 @  ip<- r2 - 32
4952    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4953    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4954    b       .LOP_USHR_LONG_finish
4955
4956/* ------------------------------ */
4957    .balign 64
4958.L_OP_ADD_FLOAT: /* 0xa6 */
4959/* File: arm-vfp/OP_ADD_FLOAT.S */
4960/* File: arm-vfp/fbinop.S */
4961    /*
4962     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4963     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4964     * use the "softfp" ABI, this must be an instruction, not a function call.
4965     *
4966     * For: add-float, sub-float, mul-float, div-float
4967     */
4968    /* floatop vAA, vBB, vCC */
4969    FETCH(r0, 1)                        @ r0<- CCBB
4970    mov     r9, rINST, lsr #8           @ r9<- AA
4971    mov     r3, r0, lsr #8              @ r3<- CC
4972    and     r2, r0, #255                @ r2<- BB
4973    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4974    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4975    flds    s1, [r3]                    @ s1<- vCC
4976    flds    s0, [r2]                    @ s0<- vBB
4977
4978    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4979    fadds   s2, s0, s1                              @ s2<- op
4980    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4981    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4982    fsts    s2, [r9]                    @ vAA<- s2
4983    GOTO_OPCODE(ip)                     @ jump to next instruction
4984
4985
4986/* ------------------------------ */
4987    .balign 64
4988.L_OP_SUB_FLOAT: /* 0xa7 */
4989/* File: arm-vfp/OP_SUB_FLOAT.S */
4990/* File: arm-vfp/fbinop.S */
4991    /*
4992     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4993     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4994     * use the "softfp" ABI, this must be an instruction, not a function call.
4995     *
4996     * For: add-float, sub-float, mul-float, div-float
4997     */
4998    /* floatop vAA, vBB, vCC */
4999    FETCH(r0, 1)                        @ r0<- CCBB
5000    mov     r9, rINST, lsr #8           @ r9<- AA
5001    mov     r3, r0, lsr #8              @ r3<- CC
5002    and     r2, r0, #255                @ r2<- BB
5003    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5004    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5005    flds    s1, [r3]                    @ s1<- vCC
5006    flds    s0, [r2]                    @ s0<- vBB
5007
5008    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5009    fsubs   s2, s0, s1                              @ s2<- op
5010    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5011    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5012    fsts    s2, [r9]                    @ vAA<- s2
5013    GOTO_OPCODE(ip)                     @ jump to next instruction
5014
5015
5016/* ------------------------------ */
5017    .balign 64
5018.L_OP_MUL_FLOAT: /* 0xa8 */
5019/* File: arm-vfp/OP_MUL_FLOAT.S */
5020/* File: arm-vfp/fbinop.S */
5021    /*
5022     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5023     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5024     * use the "softfp" ABI, this must be an instruction, not a function call.
5025     *
5026     * For: add-float, sub-float, mul-float, div-float
5027     */
5028    /* floatop vAA, vBB, vCC */
5029    FETCH(r0, 1)                        @ r0<- CCBB
5030    mov     r9, rINST, lsr #8           @ r9<- AA
5031    mov     r3, r0, lsr #8              @ r3<- CC
5032    and     r2, r0, #255                @ r2<- BB
5033    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5034    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5035    flds    s1, [r3]                    @ s1<- vCC
5036    flds    s0, [r2]                    @ s0<- vBB
5037
5038    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5039    fmuls   s2, s0, s1                              @ s2<- op
5040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5041    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5042    fsts    s2, [r9]                    @ vAA<- s2
5043    GOTO_OPCODE(ip)                     @ jump to next instruction
5044
5045
5046/* ------------------------------ */
5047    .balign 64
5048.L_OP_DIV_FLOAT: /* 0xa9 */
5049/* File: arm-vfp/OP_DIV_FLOAT.S */
5050/* File: arm-vfp/fbinop.S */
5051    /*
5052     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5053     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5054     * use the "softfp" ABI, this must be an instruction, not a function call.
5055     *
5056     * For: add-float, sub-float, mul-float, div-float
5057     */
5058    /* floatop vAA, vBB, vCC */
5059    FETCH(r0, 1)                        @ r0<- CCBB
5060    mov     r9, rINST, lsr #8           @ r9<- AA
5061    mov     r3, r0, lsr #8              @ r3<- CC
5062    and     r2, r0, #255                @ r2<- BB
5063    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5064    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5065    flds    s1, [r3]                    @ s1<- vCC
5066    flds    s0, [r2]                    @ s0<- vBB
5067
5068    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5069    fdivs   s2, s0, s1                              @ s2<- op
5070    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5071    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5072    fsts    s2, [r9]                    @ vAA<- s2
5073    GOTO_OPCODE(ip)                     @ jump to next instruction
5074
5075
5076/* ------------------------------ */
5077    .balign 64
5078.L_OP_REM_FLOAT: /* 0xaa */
5079/* File: armv5te/OP_REM_FLOAT.S */
5080/* EABI doesn't define a float remainder function, but libm does */
5081/* File: armv5te/binop.S */
5082    /*
5083     * Generic 32-bit binary operation.  Provide an "instr" line that
5084     * specifies an instruction that performs "result = r0 op r1".
5085     * This could be an ARM instruction or a function call.  (If the result
5086     * comes back in a register other than r0, you can override "result".)
5087     *
5088     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5089     * vCC (r1).  Useful for integer division and modulus.  Note that we
5090     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5091     * handles it correctly.
5092     *
5093     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5094     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5095     *      mul-float, div-float, rem-float
5096     */
5097    /* binop vAA, vBB, vCC */
5098    FETCH(r0, 1)                        @ r0<- CCBB
5099    mov     r9, rINST, lsr #8           @ r9<- AA
5100    mov     r3, r0, lsr #8              @ r3<- CC
5101    and     r2, r0, #255                @ r2<- BB
5102    GET_VREG(r1, r3)                    @ r1<- vCC
5103    GET_VREG(r0, r2)                    @ r0<- vBB
5104    .if 0
5105    cmp     r1, #0                      @ is second operand zero?
5106    beq     common_errDivideByZero
5107    .endif
5108
5109    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5110                               @ optional op; may set condition codes
5111    bl      fmodf                              @ r0<- op, r0-r3 changed
5112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5113    SET_VREG(r0, r9)               @ vAA<- r0
5114    GOTO_OPCODE(ip)                     @ jump to next instruction
5115    /* 11-14 instructions */
5116
5117
5118
5119/* ------------------------------ */
5120    .balign 64
5121.L_OP_ADD_DOUBLE: /* 0xab */
5122/* File: arm-vfp/OP_ADD_DOUBLE.S */
5123/* File: arm-vfp/fbinopWide.S */
5124    /*
5125     * Generic 64-bit double-precision floating point binary operation.
5126     * Provide an "instr" line that specifies an instruction that performs
5127     * "d2 = d0 op d1".
5128     *
5129     * for: add-double, sub-double, mul-double, div-double
5130     */
5131    /* doubleop vAA, vBB, vCC */
5132    FETCH(r0, 1)                        @ r0<- CCBB
5133    mov     r9, rINST, lsr #8           @ r9<- AA
5134    mov     r3, r0, lsr #8              @ r3<- CC
5135    and     r2, r0, #255                @ r2<- BB
5136    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5137    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5138    fldd    d1, [r3]                    @ d1<- vCC
5139    fldd    d0, [r2]                    @ d0<- vBB
5140
5141    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5142    faddd   d2, d0, d1                              @ s2<- op
5143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5144    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5145    fstd    d2, [r9]                    @ vAA<- d2
5146    GOTO_OPCODE(ip)                     @ jump to next instruction
5147
5148
5149/* ------------------------------ */
5150    .balign 64
5151.L_OP_SUB_DOUBLE: /* 0xac */
5152/* File: arm-vfp/OP_SUB_DOUBLE.S */
5153/* File: arm-vfp/fbinopWide.S */
5154    /*
5155     * Generic 64-bit double-precision floating point binary operation.
5156     * Provide an "instr" line that specifies an instruction that performs
5157     * "d2 = d0 op d1".
5158     *
5159     * for: add-double, sub-double, mul-double, div-double
5160     */
5161    /* doubleop vAA, vBB, vCC */
5162    FETCH(r0, 1)                        @ r0<- CCBB
5163    mov     r9, rINST, lsr #8           @ r9<- AA
5164    mov     r3, r0, lsr #8              @ r3<- CC
5165    and     r2, r0, #255                @ r2<- BB
5166    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5167    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5168    fldd    d1, [r3]                    @ d1<- vCC
5169    fldd    d0, [r2]                    @ d0<- vBB
5170
5171    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5172    fsubd   d2, d0, d1                              @ s2<- op
5173    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5174    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5175    fstd    d2, [r9]                    @ vAA<- d2
5176    GOTO_OPCODE(ip)                     @ jump to next instruction
5177
5178
5179/* ------------------------------ */
5180    .balign 64
5181.L_OP_MUL_DOUBLE: /* 0xad */
5182/* File: arm-vfp/OP_MUL_DOUBLE.S */
5183/* File: arm-vfp/fbinopWide.S */
5184    /*
5185     * Generic 64-bit double-precision floating point binary operation.
5186     * Provide an "instr" line that specifies an instruction that performs
5187     * "d2 = d0 op d1".
5188     *
5189     * for: add-double, sub-double, mul-double, div-double
5190     */
5191    /* doubleop vAA, vBB, vCC */
5192    FETCH(r0, 1)                        @ r0<- CCBB
5193    mov     r9, rINST, lsr #8           @ r9<- AA
5194    mov     r3, r0, lsr #8              @ r3<- CC
5195    and     r2, r0, #255                @ r2<- BB
5196    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5197    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5198    fldd    d1, [r3]                    @ d1<- vCC
5199    fldd    d0, [r2]                    @ d0<- vBB
5200
5201    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5202    fmuld   d2, d0, d1                              @ s2<- op
5203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5204    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5205    fstd    d2, [r9]                    @ vAA<- d2
5206    GOTO_OPCODE(ip)                     @ jump to next instruction
5207
5208
5209/* ------------------------------ */
5210    .balign 64
5211.L_OP_DIV_DOUBLE: /* 0xae */
5212/* File: arm-vfp/OP_DIV_DOUBLE.S */
5213/* File: arm-vfp/fbinopWide.S */
5214    /*
5215     * Generic 64-bit double-precision floating point binary operation.
5216     * Provide an "instr" line that specifies an instruction that performs
5217     * "d2 = d0 op d1".
5218     *
5219     * for: add-double, sub-double, mul-double, div-double
5220     */
5221    /* doubleop vAA, vBB, vCC */
5222    FETCH(r0, 1)                        @ r0<- CCBB
5223    mov     r9, rINST, lsr #8           @ r9<- AA
5224    mov     r3, r0, lsr #8              @ r3<- CC
5225    and     r2, r0, #255                @ r2<- BB
5226    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5227    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5228    fldd    d1, [r3]                    @ d1<- vCC
5229    fldd    d0, [r2]                    @ d0<- vBB
5230
5231    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5232    fdivd   d2, d0, d1                              @ s2<- op
5233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5234    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5235    fstd    d2, [r9]                    @ vAA<- d2
5236    GOTO_OPCODE(ip)                     @ jump to next instruction
5237
5238
5239/* ------------------------------ */
5240    .balign 64
5241.L_OP_REM_DOUBLE: /* 0xaf */
5242/* File: armv5te/OP_REM_DOUBLE.S */
5243/* EABI doesn't define a double remainder function, but libm does */
5244/* File: armv5te/binopWide.S */
5245    /*
5246     * Generic 64-bit binary operation.  Provide an "instr" line that
5247     * specifies an instruction that performs "result = r0-r1 op r2-r3".
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-long, sub-long, div-long, rem-long, and-long, or-long,
5255     *      xor-long, add-double, sub-double, mul-double, div-double,
5256     *      rem-double
5257     *
5258     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5259     */
5260    /* binop vAA, vBB, vCC */
5261    FETCH(r0, 1)                        @ r0<- CCBB
5262    mov     r9, rINST, lsr #8           @ r9<- AA
5263    and     r2, r0, #255                @ r2<- BB
5264    mov     r3, r0, lsr #8              @ r3<- CC
5265    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5266    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5267    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5268    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5269    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5270    .if 0
5271    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5272    beq     common_errDivideByZero
5273    .endif
5274    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5275
5276                               @ optional op; may set condition codes
5277    bl      fmod                              @ result<- op, r0-r3 changed
5278    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5279    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5280    GOTO_OPCODE(ip)                     @ jump to next instruction
5281    /* 14-17 instructions */
5282
5283
5284
5285/* ------------------------------ */
5286    .balign 64
5287.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5288/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5289/* File: armv6t2/binop2addr.S */
5290    /*
5291     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5292     * that specifies an instruction that performs "result = r0 op r1".
5293     * This could be an ARM instruction or a function call.  (If the result
5294     * comes back in a register other than r0, you can override "result".)
5295     *
5296     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5297     * vCC (r1).  Useful for integer division and modulus.
5298     *
5299     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5300     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5301     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5302     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5303     */
5304    /* binop/2addr vA, vB */
5305    mov     r3, rINST, lsr #12          @ r3<- B
5306    ubfx    r9, rINST, #8, #4           @ r9<- A
5307    GET_VREG(r1, r3)                    @ r1<- vB
5308    GET_VREG(r0, r9)                    @ r0<- vA
5309    .if 0
5310    cmp     r1, #0                      @ is second operand zero?
5311    beq     common_errDivideByZero
5312    .endif
5313    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5314
5315                               @ optional op; may set condition codes
5316    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5317    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5318    SET_VREG(r0, r9)               @ vAA<- r0
5319    GOTO_OPCODE(ip)                     @ jump to next instruction
5320    /* 10-13 instructions */
5321
5322
5323
5324/* ------------------------------ */
5325    .balign 64
5326.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5327/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5328/* File: armv6t2/binop2addr.S */
5329    /*
5330     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5331     * that specifies an instruction that performs "result = r0 op r1".
5332     * This could be an ARM instruction or a function call.  (If the result
5333     * comes back in a register other than r0, you can override "result".)
5334     *
5335     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5336     * vCC (r1).  Useful for integer division and modulus.
5337     *
5338     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5339     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5340     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5341     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5342     */
5343    /* binop/2addr vA, vB */
5344    mov     r3, rINST, lsr #12          @ r3<- B
5345    ubfx    r9, rINST, #8, #4           @ r9<- A
5346    GET_VREG(r1, r3)                    @ r1<- vB
5347    GET_VREG(r0, r9)                    @ r0<- vA
5348    .if 0
5349    cmp     r1, #0                      @ is second operand zero?
5350    beq     common_errDivideByZero
5351    .endif
5352    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5353
5354                               @ optional op; may set condition codes
5355    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5357    SET_VREG(r0, r9)               @ vAA<- r0
5358    GOTO_OPCODE(ip)                     @ jump to next instruction
5359    /* 10-13 instructions */
5360
5361
5362
5363/* ------------------------------ */
5364    .balign 64
5365.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5366/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5367/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5368/* File: armv6t2/binop2addr.S */
5369    /*
5370     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5371     * that specifies an instruction that performs "result = r0 op r1".
5372     * This could be an ARM instruction or a function call.  (If the result
5373     * comes back in a register other than r0, you can override "result".)
5374     *
5375     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5376     * vCC (r1).  Useful for integer division and modulus.
5377     *
5378     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5379     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5380     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5381     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5382     */
5383    /* binop/2addr vA, vB */
5384    mov     r3, rINST, lsr #12          @ r3<- B
5385    ubfx    r9, rINST, #8, #4           @ r9<- A
5386    GET_VREG(r1, r3)                    @ r1<- vB
5387    GET_VREG(r0, r9)                    @ r0<- vA
5388    .if 0
5389    cmp     r1, #0                      @ is second operand zero?
5390    beq     common_errDivideByZero
5391    .endif
5392    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5393
5394                               @ optional op; may set condition codes
5395    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5397    SET_VREG(r0, r9)               @ vAA<- r0
5398    GOTO_OPCODE(ip)                     @ jump to next instruction
5399    /* 10-13 instructions */
5400
5401
5402
5403/* ------------------------------ */
5404    .balign 64
5405.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5406/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5407/* File: armv6t2/binop2addr.S */
5408    /*
5409     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5410     * that specifies an instruction that performs "result = r0 op r1".
5411     * This could be an ARM instruction or a function call.  (If the result
5412     * comes back in a register other than r0, you can override "result".)
5413     *
5414     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5415     * vCC (r1).  Useful for integer division and modulus.
5416     *
5417     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5418     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5419     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5420     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5421     */
5422    /* binop/2addr vA, vB */
5423    mov     r3, rINST, lsr #12          @ r3<- B
5424    ubfx    r9, rINST, #8, #4           @ r9<- A
5425    GET_VREG(r1, r3)                    @ r1<- vB
5426    GET_VREG(r0, r9)                    @ r0<- vA
5427    .if 1
5428    cmp     r1, #0                      @ is second operand zero?
5429    beq     common_errDivideByZero
5430    .endif
5431    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5432
5433                               @ optional op; may set condition codes
5434    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5435    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5436    SET_VREG(r0, r9)               @ vAA<- r0
5437    GOTO_OPCODE(ip)                     @ jump to next instruction
5438    /* 10-13 instructions */
5439
5440
5441
5442/* ------------------------------ */
5443    .balign 64
5444.L_OP_REM_INT_2ADDR: /* 0xb4 */
5445/* File: armv6t2/OP_REM_INT_2ADDR.S */
5446/* idivmod returns quotient in r0 and remainder in r1 */
5447/* File: armv6t2/binop2addr.S */
5448    /*
5449     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5450     * that specifies an instruction that performs "result = r0 op r1".
5451     * This could be an ARM instruction or a function call.  (If the result
5452     * comes back in a register other than r0, you can override "result".)
5453     *
5454     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5455     * vCC (r1).  Useful for integer division and modulus.
5456     *
5457     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5458     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5459     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5460     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5461     */
5462    /* binop/2addr vA, vB */
5463    mov     r3, rINST, lsr #12          @ r3<- B
5464    ubfx    r9, rINST, #8, #4           @ r9<- A
5465    GET_VREG(r1, r3)                    @ r1<- vB
5466    GET_VREG(r0, r9)                    @ r0<- vA
5467    .if 1
5468    cmp     r1, #0                      @ is second operand zero?
5469    beq     common_errDivideByZero
5470    .endif
5471    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5472
5473                               @ optional op; may set condition codes
5474    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5475    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5476    SET_VREG(r1, r9)               @ vAA<- r1
5477    GOTO_OPCODE(ip)                     @ jump to next instruction
5478    /* 10-13 instructions */
5479
5480
5481
5482/* ------------------------------ */
5483    .balign 64
5484.L_OP_AND_INT_2ADDR: /* 0xb5 */
5485/* File: armv6t2/OP_AND_INT_2ADDR.S */
5486/* File: armv6t2/binop2addr.S */
5487    /*
5488     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5489     * that specifies an instruction that performs "result = r0 op r1".
5490     * This could be an ARM instruction or a function call.  (If the result
5491     * comes back in a register other than r0, you can override "result".)
5492     *
5493     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5494     * vCC (r1).  Useful for integer division and modulus.
5495     *
5496     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5497     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5498     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5499     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5500     */
5501    /* binop/2addr vA, vB */
5502    mov     r3, rINST, lsr #12          @ r3<- B
5503    ubfx    r9, rINST, #8, #4           @ r9<- A
5504    GET_VREG(r1, r3)                    @ r1<- vB
5505    GET_VREG(r0, r9)                    @ r0<- vA
5506    .if 0
5507    cmp     r1, #0                      @ is second operand zero?
5508    beq     common_errDivideByZero
5509    .endif
5510    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5511
5512                               @ optional op; may set condition codes
5513    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5514    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5515    SET_VREG(r0, r9)               @ vAA<- r0
5516    GOTO_OPCODE(ip)                     @ jump to next instruction
5517    /* 10-13 instructions */
5518
5519
5520
5521/* ------------------------------ */
5522    .balign 64
5523.L_OP_OR_INT_2ADDR: /* 0xb6 */
5524/* File: armv6t2/OP_OR_INT_2ADDR.S */
5525/* File: armv6t2/binop2addr.S */
5526    /*
5527     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5528     * that specifies an instruction that performs "result = r0 op r1".
5529     * This could be an ARM instruction or a function call.  (If the result
5530     * comes back in a register other than r0, you can override "result".)
5531     *
5532     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5533     * vCC (r1).  Useful for integer division and modulus.
5534     *
5535     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5536     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5537     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5538     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5539     */
5540    /* binop/2addr vA, vB */
5541    mov     r3, rINST, lsr #12          @ r3<- B
5542    ubfx    r9, rINST, #8, #4           @ r9<- A
5543    GET_VREG(r1, r3)                    @ r1<- vB
5544    GET_VREG(r0, r9)                    @ r0<- vA
5545    .if 0
5546    cmp     r1, #0                      @ is second operand zero?
5547    beq     common_errDivideByZero
5548    .endif
5549    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5550
5551                               @ optional op; may set condition codes
5552    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5553    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5554    SET_VREG(r0, r9)               @ vAA<- r0
5555    GOTO_OPCODE(ip)                     @ jump to next instruction
5556    /* 10-13 instructions */
5557
5558
5559
5560/* ------------------------------ */
5561    .balign 64
5562.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5563/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5564/* File: armv6t2/binop2addr.S */
5565    /*
5566     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5567     * that specifies an instruction that performs "result = r0 op r1".
5568     * This could be an ARM instruction or a function call.  (If the result
5569     * comes back in a register other than r0, you can override "result".)
5570     *
5571     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5572     * vCC (r1).  Useful for integer division and modulus.
5573     *
5574     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5575     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5576     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5577     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5578     */
5579    /* binop/2addr vA, vB */
5580    mov     r3, rINST, lsr #12          @ r3<- B
5581    ubfx    r9, rINST, #8, #4           @ r9<- A
5582    GET_VREG(r1, r3)                    @ r1<- vB
5583    GET_VREG(r0, r9)                    @ r0<- vA
5584    .if 0
5585    cmp     r1, #0                      @ is second operand zero?
5586    beq     common_errDivideByZero
5587    .endif
5588    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5589
5590                               @ optional op; may set condition codes
5591    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5592    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5593    SET_VREG(r0, r9)               @ vAA<- r0
5594    GOTO_OPCODE(ip)                     @ jump to next instruction
5595    /* 10-13 instructions */
5596
5597
5598
5599/* ------------------------------ */
5600    .balign 64
5601.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5602/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5603/* File: armv6t2/binop2addr.S */
5604    /*
5605     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5606     * that specifies an instruction that performs "result = r0 op r1".
5607     * This could be an ARM instruction or a function call.  (If the result
5608     * comes back in a register other than r0, you can override "result".)
5609     *
5610     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5611     * vCC (r1).  Useful for integer division and modulus.
5612     *
5613     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5614     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5615     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5616     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5617     */
5618    /* binop/2addr vA, vB */
5619    mov     r3, rINST, lsr #12          @ r3<- B
5620    ubfx    r9, rINST, #8, #4           @ r9<- A
5621    GET_VREG(r1, r3)                    @ r1<- vB
5622    GET_VREG(r0, r9)                    @ r0<- vA
5623    .if 0
5624    cmp     r1, #0                      @ is second operand zero?
5625    beq     common_errDivideByZero
5626    .endif
5627    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5628
5629    and     r1, r1, #31                           @ optional op; may set condition codes
5630    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5631    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5632    SET_VREG(r0, r9)               @ vAA<- r0
5633    GOTO_OPCODE(ip)                     @ jump to next instruction
5634    /* 10-13 instructions */
5635
5636
5637
5638/* ------------------------------ */
5639    .balign 64
5640.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5641/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5642/* File: armv6t2/binop2addr.S */
5643    /*
5644     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5645     * that specifies an instruction that performs "result = r0 op r1".
5646     * This could be an ARM instruction or a function call.  (If the result
5647     * comes back in a register other than r0, you can override "result".)
5648     *
5649     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5650     * vCC (r1).  Useful for integer division and modulus.
5651     *
5652     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5653     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5654     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5655     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5656     */
5657    /* binop/2addr vA, vB */
5658    mov     r3, rINST, lsr #12          @ r3<- B
5659    ubfx    r9, rINST, #8, #4           @ r9<- A
5660    GET_VREG(r1, r3)                    @ r1<- vB
5661    GET_VREG(r0, r9)                    @ r0<- vA
5662    .if 0
5663    cmp     r1, #0                      @ is second operand zero?
5664    beq     common_errDivideByZero
5665    .endif
5666    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5667
5668    and     r1, r1, #31                           @ optional op; may set condition codes
5669    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5670    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5671    SET_VREG(r0, r9)               @ vAA<- r0
5672    GOTO_OPCODE(ip)                     @ jump to next instruction
5673    /* 10-13 instructions */
5674
5675
5676
5677/* ------------------------------ */
5678    .balign 64
5679.L_OP_USHR_INT_2ADDR: /* 0xba */
5680/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5681/* File: armv6t2/binop2addr.S */
5682    /*
5683     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5684     * that specifies an instruction that performs "result = r0 op r1".
5685     * This could be an ARM instruction or a function call.  (If the result
5686     * comes back in a register other than r0, you can override "result".)
5687     *
5688     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5689     * vCC (r1).  Useful for integer division and modulus.
5690     *
5691     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5692     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5693     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5694     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5695     */
5696    /* binop/2addr vA, vB */
5697    mov     r3, rINST, lsr #12          @ r3<- B
5698    ubfx    r9, rINST, #8, #4           @ r9<- A
5699    GET_VREG(r1, r3)                    @ r1<- vB
5700    GET_VREG(r0, r9)                    @ r0<- vA
5701    .if 0
5702    cmp     r1, #0                      @ is second operand zero?
5703    beq     common_errDivideByZero
5704    .endif
5705    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5706
5707    and     r1, r1, #31                           @ optional op; may set condition codes
5708    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5709    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5710    SET_VREG(r0, r9)               @ vAA<- r0
5711    GOTO_OPCODE(ip)                     @ jump to next instruction
5712    /* 10-13 instructions */
5713
5714
5715
5716/* ------------------------------ */
5717    .balign 64
5718.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5719/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5720/* File: armv6t2/binopWide2addr.S */
5721    /*
5722     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5723     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5724     * This could be an ARM instruction or a function call.  (If the result
5725     * comes back in a register other than r0, you can override "result".)
5726     *
5727     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5728     * vCC (r1).  Useful for integer division and modulus.
5729     *
5730     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5731     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5732     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5733     *      rem-double/2addr
5734     */
5735    /* binop/2addr vA, vB */
5736    mov     r1, rINST, lsr #12          @ r1<- B
5737    ubfx    r9, rINST, #8, #4           @ r9<- A
5738    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5739    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5740    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5741    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5742    .if 0
5743    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5744    beq     common_errDivideByZero
5745    .endif
5746    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5747
5748    adds    r0, r0, r2                           @ optional op; may set condition codes
5749    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5751    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5752    GOTO_OPCODE(ip)                     @ jump to next instruction
5753    /* 12-15 instructions */
5754
5755
5756
5757/* ------------------------------ */
5758    .balign 64
5759.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5760/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5761/* File: armv6t2/binopWide2addr.S */
5762    /*
5763     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5764     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5765     * This could be an ARM instruction or a function call.  (If the result
5766     * comes back in a register other than r0, you can override "result".)
5767     *
5768     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5769     * vCC (r1).  Useful for integer division and modulus.
5770     *
5771     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5772     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5773     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5774     *      rem-double/2addr
5775     */
5776    /* binop/2addr vA, vB */
5777    mov     r1, rINST, lsr #12          @ r1<- B
5778    ubfx    r9, rINST, #8, #4           @ r9<- A
5779    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5780    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5781    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5782    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5783    .if 0
5784    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5785    beq     common_errDivideByZero
5786    .endif
5787    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5788
5789    subs    r0, r0, r2                           @ optional op; may set condition codes
5790    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5792    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5793    GOTO_OPCODE(ip)                     @ jump to next instruction
5794    /* 12-15 instructions */
5795
5796
5797
5798/* ------------------------------ */
5799    .balign 64
5800.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5801/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5802    /*
5803     * Signed 64-bit integer multiply, "/2addr" version.
5804     *
5805     * See OP_MUL_LONG for an explanation.
5806     *
5807     * We get a little tight on registers, so to avoid looking up &fp[A]
5808     * again we stuff it into rINST.
5809     */
5810    /* mul-long/2addr vA, vB */
5811    mov     r1, rINST, lsr #12          @ r1<- B
5812    ubfx    r9, rINST, #8, #4           @ r9<- A
5813    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5814    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5815    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5816    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5817    mul     ip, r2, r1                  @  ip<- ZxW
5818    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5819    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5820    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5821    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5822    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5823    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5824    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5825    GOTO_OPCODE(ip)                     @ jump to next instruction
5826
5827
5828/* ------------------------------ */
5829    .balign 64
5830.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5831/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5832/* File: armv6t2/binopWide2addr.S */
5833    /*
5834     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5835     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5836     * This could be an ARM instruction or a function call.  (If the result
5837     * comes back in a register other than r0, you can override "result".)
5838     *
5839     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5840     * vCC (r1).  Useful for integer division and modulus.
5841     *
5842     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5843     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5844     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5845     *      rem-double/2addr
5846     */
5847    /* binop/2addr vA, vB */
5848    mov     r1, rINST, lsr #12          @ r1<- B
5849    ubfx    r9, rINST, #8, #4           @ r9<- A
5850    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5851    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5852    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5853    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5854    .if 1
5855    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5856    beq     common_errDivideByZero
5857    .endif
5858    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5859
5860                               @ optional op; may set condition codes
5861    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5863    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5864    GOTO_OPCODE(ip)                     @ jump to next instruction
5865    /* 12-15 instructions */
5866
5867
5868
5869/* ------------------------------ */
5870    .balign 64
5871.L_OP_REM_LONG_2ADDR: /* 0xbf */
5872/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5873/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5874/* File: armv6t2/binopWide2addr.S */
5875    /*
5876     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5877     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5878     * This could be an ARM instruction or a function call.  (If the result
5879     * comes back in a register other than r0, you can override "result".)
5880     *
5881     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5882     * vCC (r1).  Useful for integer division and modulus.
5883     *
5884     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5885     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5886     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5887     *      rem-double/2addr
5888     */
5889    /* binop/2addr vA, vB */
5890    mov     r1, rINST, lsr #12          @ r1<- B
5891    ubfx    r9, rINST, #8, #4           @ r9<- A
5892    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5893    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5894    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5895    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5896    .if 1
5897    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5898    beq     common_errDivideByZero
5899    .endif
5900    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5901
5902                               @ optional op; may set condition codes
5903    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5905    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5906    GOTO_OPCODE(ip)                     @ jump to next instruction
5907    /* 12-15 instructions */
5908
5909
5910
5911/* ------------------------------ */
5912    .balign 64
5913.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5914/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5915/* File: armv6t2/binopWide2addr.S */
5916    /*
5917     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5918     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5919     * This could be an ARM instruction or a function call.  (If the result
5920     * comes back in a register other than r0, you can override "result".)
5921     *
5922     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5923     * vCC (r1).  Useful for integer division and modulus.
5924     *
5925     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5926     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5927     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5928     *      rem-double/2addr
5929     */
5930    /* binop/2addr vA, vB */
5931    mov     r1, rINST, lsr #12          @ r1<- B
5932    ubfx    r9, rINST, #8, #4           @ r9<- A
5933    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5934    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5935    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5936    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5937    .if 0
5938    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5939    beq     common_errDivideByZero
5940    .endif
5941    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5942
5943    and     r0, r0, r2                           @ optional op; may set condition codes
5944    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5946    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5947    GOTO_OPCODE(ip)                     @ jump to next instruction
5948    /* 12-15 instructions */
5949
5950
5951
5952/* ------------------------------ */
5953    .balign 64
5954.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5955/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5956/* File: armv6t2/binopWide2addr.S */
5957    /*
5958     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5959     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5960     * This could be an ARM instruction or a function call.  (If the result
5961     * comes back in a register other than r0, you can override "result".)
5962     *
5963     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5964     * vCC (r1).  Useful for integer division and modulus.
5965     *
5966     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5967     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5968     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5969     *      rem-double/2addr
5970     */
5971    /* binop/2addr vA, vB */
5972    mov     r1, rINST, lsr #12          @ r1<- B
5973    ubfx    r9, rINST, #8, #4           @ r9<- A
5974    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5975    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5976    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5977    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5978    .if 0
5979    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5980    beq     common_errDivideByZero
5981    .endif
5982    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5983
5984    orr     r0, r0, r2                           @ optional op; may set condition codes
5985    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5987    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5988    GOTO_OPCODE(ip)                     @ jump to next instruction
5989    /* 12-15 instructions */
5990
5991
5992
5993/* ------------------------------ */
5994    .balign 64
5995.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5996/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5997/* File: armv6t2/binopWide2addr.S */
5998    /*
5999     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6000     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6001     * This could be an ARM instruction or a function call.  (If the result
6002     * comes back in a register other than r0, you can override "result".)
6003     *
6004     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6005     * vCC (r1).  Useful for integer division and modulus.
6006     *
6007     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6008     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6009     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6010     *      rem-double/2addr
6011     */
6012    /* binop/2addr vA, vB */
6013    mov     r1, rINST, lsr #12          @ r1<- B
6014    ubfx    r9, rINST, #8, #4           @ r9<- A
6015    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6016    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6017    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6018    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6019    .if 0
6020    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6021    beq     common_errDivideByZero
6022    .endif
6023    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6024
6025    eor     r0, r0, r2                           @ optional op; may set condition codes
6026    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6028    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6029    GOTO_OPCODE(ip)                     @ jump to next instruction
6030    /* 12-15 instructions */
6031
6032
6033
6034/* ------------------------------ */
6035    .balign 64
6036.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6037/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6038    /*
6039     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6040     * 32-bit shift distance.
6041     */
6042    /* shl-long/2addr vA, vB */
6043    mov     r3, rINST, lsr #12          @ r3<- B
6044    ubfx    r9, rINST, #8, #4           @ r9<- A
6045    GET_VREG(r2, r3)                    @ r2<- vB
6046    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6047    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6048    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6049
6050    mov     r1, r1, asl r2              @  r1<- r1 << r2
6051    rsb     r3, r2, #32                 @  r3<- 32 - r2
6052    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6053    subs    ip, r2, #32                 @  ip<- r2 - 32
6054    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6055    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6056    mov     r0, r0, asl r2              @  r0<- r0 << r2
6057    b       .LOP_SHL_LONG_2ADDR_finish
6058
6059/* ------------------------------ */
6060    .balign 64
6061.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6062/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6063    /*
6064     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6065     * 32-bit shift distance.
6066     */
6067    /* shr-long/2addr vA, vB */
6068    mov     r3, rINST, lsr #12          @ r3<- B
6069    ubfx    r9, rINST, #8, #4           @ r9<- A
6070    GET_VREG(r2, r3)                    @ r2<- vB
6071    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6072    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6073    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6074
6075    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6076    rsb     r3, r2, #32                 @  r3<- 32 - r2
6077    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6078    subs    ip, r2, #32                 @  ip<- r2 - 32
6079    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6080    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6081    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6082    b       .LOP_SHR_LONG_2ADDR_finish
6083
6084/* ------------------------------ */
6085    .balign 64
6086.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6087/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6088    /*
6089     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6090     * 32-bit shift distance.
6091     */
6092    /* ushr-long/2addr vA, vB */
6093    mov     r3, rINST, lsr #12          @ r3<- B
6094    ubfx    r9, rINST, #8, #4           @ r9<- A
6095    GET_VREG(r2, r3)                    @ r2<- vB
6096    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6097    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6098    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6099
6100    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6101    rsb     r3, r2, #32                 @  r3<- 32 - r2
6102    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6103    subs    ip, r2, #32                 @  ip<- r2 - 32
6104    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6105    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6106    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6107    b       .LOP_USHR_LONG_2ADDR_finish
6108
6109/* ------------------------------ */
6110    .balign 64
6111.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6112/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6113/* File: arm-vfp/fbinop2addr.S */
6114    /*
6115     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6116     * an "instr" line that specifies an instruction that performs
6117     * "s2 = s0 op s1".
6118     *
6119     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6120     */
6121    /* binop/2addr vA, vB */
6122    mov     r3, rINST, lsr #12          @ r3<- B
6123    mov     r9, rINST, lsr #8           @ r9<- A+
6124    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6125    and     r9, r9, #15                 @ r9<- A
6126    flds    s1, [r3]                    @ s1<- vB
6127    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6128    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6129    flds    s0, [r9]                    @ s0<- vA
6130
6131    fadds   s2, s0, s1                              @ s2<- op
6132    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6133    fsts    s2, [r9]                    @ vAA<- s2
6134    GOTO_OPCODE(ip)                     @ jump to next instruction
6135
6136
6137/* ------------------------------ */
6138    .balign 64
6139.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6140/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6141/* File: arm-vfp/fbinop2addr.S */
6142    /*
6143     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6144     * an "instr" line that specifies an instruction that performs
6145     * "s2 = s0 op s1".
6146     *
6147     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6148     */
6149    /* binop/2addr vA, vB */
6150    mov     r3, rINST, lsr #12          @ r3<- B
6151    mov     r9, rINST, lsr #8           @ r9<- A+
6152    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6153    and     r9, r9, #15                 @ r9<- A
6154    flds    s1, [r3]                    @ s1<- vB
6155    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6156    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6157    flds    s0, [r9]                    @ s0<- vA
6158
6159    fsubs   s2, s0, s1                              @ s2<- op
6160    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6161    fsts    s2, [r9]                    @ vAA<- s2
6162    GOTO_OPCODE(ip)                     @ jump to next instruction
6163
6164
6165/* ------------------------------ */
6166    .balign 64
6167.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6168/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6169/* File: arm-vfp/fbinop2addr.S */
6170    /*
6171     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6172     * an "instr" line that specifies an instruction that performs
6173     * "s2 = s0 op s1".
6174     *
6175     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6176     */
6177    /* binop/2addr vA, vB */
6178    mov     r3, rINST, lsr #12          @ r3<- B
6179    mov     r9, rINST, lsr #8           @ r9<- A+
6180    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6181    and     r9, r9, #15                 @ r9<- A
6182    flds    s1, [r3]                    @ s1<- vB
6183    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6184    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6185    flds    s0, [r9]                    @ s0<- vA
6186
6187    fmuls   s2, s0, s1                              @ s2<- op
6188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6189    fsts    s2, [r9]                    @ vAA<- s2
6190    GOTO_OPCODE(ip)                     @ jump to next instruction
6191
6192
6193/* ------------------------------ */
6194    .balign 64
6195.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6196/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6197/* File: arm-vfp/fbinop2addr.S */
6198    /*
6199     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6200     * an "instr" line that specifies an instruction that performs
6201     * "s2 = s0 op s1".
6202     *
6203     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6204     */
6205    /* binop/2addr vA, vB */
6206    mov     r3, rINST, lsr #12          @ r3<- B
6207    mov     r9, rINST, lsr #8           @ r9<- A+
6208    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6209    and     r9, r9, #15                 @ r9<- A
6210    flds    s1, [r3]                    @ s1<- vB
6211    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6212    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6213    flds    s0, [r9]                    @ s0<- vA
6214
6215    fdivs   s2, s0, s1                              @ s2<- op
6216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6217    fsts    s2, [r9]                    @ vAA<- s2
6218    GOTO_OPCODE(ip)                     @ jump to next instruction
6219
6220
6221/* ------------------------------ */
6222    .balign 64
6223.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6224/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6225/* EABI doesn't define a float remainder function, but libm does */
6226/* File: armv6t2/binop2addr.S */
6227    /*
6228     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6229     * that specifies an instruction that performs "result = r0 op r1".
6230     * This could be an ARM instruction or a function call.  (If the result
6231     * comes back in a register other than r0, you can override "result".)
6232     *
6233     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6234     * vCC (r1).  Useful for integer division and modulus.
6235     *
6236     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6237     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6238     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6239     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6240     */
6241    /* binop/2addr vA, vB */
6242    mov     r3, rINST, lsr #12          @ r3<- B
6243    ubfx    r9, rINST, #8, #4           @ r9<- A
6244    GET_VREG(r1, r3)                    @ r1<- vB
6245    GET_VREG(r0, r9)                    @ r0<- vA
6246    .if 0
6247    cmp     r1, #0                      @ is second operand zero?
6248    beq     common_errDivideByZero
6249    .endif
6250    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6251
6252                               @ optional op; may set condition codes
6253    bl      fmodf                              @ r0<- op, r0-r3 changed
6254    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6255    SET_VREG(r0, r9)               @ vAA<- r0
6256    GOTO_OPCODE(ip)                     @ jump to next instruction
6257    /* 10-13 instructions */
6258
6259
6260
6261/* ------------------------------ */
6262    .balign 64
6263.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6264/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6265/* File: arm-vfp/fbinopWide2addr.S */
6266    /*
6267     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6268     * an "instr" line that specifies an instruction that performs
6269     * "d2 = d0 op d1".
6270     *
6271     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6272     *      div-double/2addr
6273     */
6274    /* binop/2addr vA, vB */
6275    mov     r3, rINST, lsr #12          @ r3<- B
6276    mov     r9, rINST, lsr #8           @ r9<- A+
6277    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6278    and     r9, r9, #15                 @ r9<- A
6279    fldd    d1, [r3]                    @ d1<- vB
6280    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6281    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6282    fldd    d0, [r9]                    @ d0<- vA
6283
6284    faddd   d2, d0, d1                              @ d2<- op
6285    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6286    fstd    d2, [r9]                    @ vAA<- d2
6287    GOTO_OPCODE(ip)                     @ jump to next instruction
6288
6289
6290/* ------------------------------ */
6291    .balign 64
6292.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6293/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6294/* File: arm-vfp/fbinopWide2addr.S */
6295    /*
6296     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6297     * an "instr" line that specifies an instruction that performs
6298     * "d2 = d0 op d1".
6299     *
6300     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6301     *      div-double/2addr
6302     */
6303    /* binop/2addr vA, vB */
6304    mov     r3, rINST, lsr #12          @ r3<- B
6305    mov     r9, rINST, lsr #8           @ r9<- A+
6306    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6307    and     r9, r9, #15                 @ r9<- A
6308    fldd    d1, [r3]                    @ d1<- vB
6309    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6310    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6311    fldd    d0, [r9]                    @ d0<- vA
6312
6313    fsubd   d2, d0, d1                              @ d2<- op
6314    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6315    fstd    d2, [r9]                    @ vAA<- d2
6316    GOTO_OPCODE(ip)                     @ jump to next instruction
6317
6318
6319/* ------------------------------ */
6320    .balign 64
6321.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6322/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6323/* File: arm-vfp/fbinopWide2addr.S */
6324    /*
6325     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6326     * an "instr" line that specifies an instruction that performs
6327     * "d2 = d0 op d1".
6328     *
6329     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6330     *      div-double/2addr
6331     */
6332    /* binop/2addr vA, vB */
6333    mov     r3, rINST, lsr #12          @ r3<- B
6334    mov     r9, rINST, lsr #8           @ r9<- A+
6335    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6336    and     r9, r9, #15                 @ r9<- A
6337    fldd    d1, [r3]                    @ d1<- vB
6338    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6339    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6340    fldd    d0, [r9]                    @ d0<- vA
6341
6342    fmuld   d2, d0, d1                              @ d2<- op
6343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6344    fstd    d2, [r9]                    @ vAA<- d2
6345    GOTO_OPCODE(ip)                     @ jump to next instruction
6346
6347
6348/* ------------------------------ */
6349    .balign 64
6350.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6351/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6352/* File: arm-vfp/fbinopWide2addr.S */
6353    /*
6354     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6355     * an "instr" line that specifies an instruction that performs
6356     * "d2 = d0 op d1".
6357     *
6358     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6359     *      div-double/2addr
6360     */
6361    /* binop/2addr vA, vB */
6362    mov     r3, rINST, lsr #12          @ r3<- B
6363    mov     r9, rINST, lsr #8           @ r9<- A+
6364    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6365    and     r9, r9, #15                 @ r9<- A
6366    fldd    d1, [r3]                    @ d1<- vB
6367    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6368    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6369    fldd    d0, [r9]                    @ d0<- vA
6370
6371    fdivd   d2, d0, d1                              @ d2<- op
6372    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6373    fstd    d2, [r9]                    @ vAA<- d2
6374    GOTO_OPCODE(ip)                     @ jump to next instruction
6375
6376
6377/* ------------------------------ */
6378    .balign 64
6379.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6380/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6381/* EABI doesn't define a double remainder function, but libm does */
6382/* File: armv6t2/binopWide2addr.S */
6383    /*
6384     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6385     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6386     * This could be an ARM instruction or a function call.  (If the result
6387     * comes back in a register other than r0, you can override "result".)
6388     *
6389     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6390     * vCC (r1).  Useful for integer division and modulus.
6391     *
6392     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6393     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6394     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6395     *      rem-double/2addr
6396     */
6397    /* binop/2addr vA, vB */
6398    mov     r1, rINST, lsr #12          @ r1<- B
6399    ubfx    r9, rINST, #8, #4           @ r9<- A
6400    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6401    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6402    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6403    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6404    .if 0
6405    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6406    beq     common_errDivideByZero
6407    .endif
6408    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6409
6410                               @ optional op; may set condition codes
6411    bl      fmod                              @ result<- op, r0-r3 changed
6412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6413    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6414    GOTO_OPCODE(ip)                     @ jump to next instruction
6415    /* 12-15 instructions */
6416
6417
6418
6419/* ------------------------------ */
6420    .balign 64
6421.L_OP_ADD_INT_LIT16: /* 0xd0 */
6422/* File: armv6t2/OP_ADD_INT_LIT16.S */
6423/* File: armv6t2/binopLit16.S */
6424    /*
6425     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6426     * that specifies an instruction that performs "result = r0 op r1".
6427     * This could be an ARM instruction or a function call.  (If the result
6428     * comes back in a register other than r0, you can override "result".)
6429     *
6430     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6431     * vCC (r1).  Useful for integer division and modulus.
6432     *
6433     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6434     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6435     */
6436    /* binop/lit16 vA, vB, #+CCCC */
6437    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6438    mov     r2, rINST, lsr #12          @ r2<- B
6439    ubfx    r9, rINST, #8, #4           @ r9<- A
6440    GET_VREG(r0, r2)                    @ r0<- vB
6441    .if 0
6442    cmp     r1, #0                      @ is second operand zero?
6443    beq     common_errDivideByZero
6444    .endif
6445    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6446
6447    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6448    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6449    SET_VREG(r0, r9)               @ vAA<- r0
6450    GOTO_OPCODE(ip)                     @ jump to next instruction
6451    /* 10-13 instructions */
6452
6453
6454
6455/* ------------------------------ */
6456    .balign 64
6457.L_OP_RSUB_INT: /* 0xd1 */
6458/* File: armv6t2/OP_RSUB_INT.S */
6459/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6460/* File: armv6t2/binopLit16.S */
6461    /*
6462     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6463     * that specifies an instruction that performs "result = r0 op r1".
6464     * This could be an ARM instruction or a function call.  (If the result
6465     * comes back in a register other than r0, you can override "result".)
6466     *
6467     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6468     * vCC (r1).  Useful for integer division and modulus.
6469     *
6470     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6471     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6472     */
6473    /* binop/lit16 vA, vB, #+CCCC */
6474    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6475    mov     r2, rINST, lsr #12          @ r2<- B
6476    ubfx    r9, rINST, #8, #4           @ r9<- A
6477    GET_VREG(r0, r2)                    @ r0<- vB
6478    .if 0
6479    cmp     r1, #0                      @ is second operand zero?
6480    beq     common_errDivideByZero
6481    .endif
6482    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6483
6484    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6486    SET_VREG(r0, r9)               @ vAA<- r0
6487    GOTO_OPCODE(ip)                     @ jump to next instruction
6488    /* 10-13 instructions */
6489
6490
6491
6492/* ------------------------------ */
6493    .balign 64
6494.L_OP_MUL_INT_LIT16: /* 0xd2 */
6495/* File: armv6t2/OP_MUL_INT_LIT16.S */
6496/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6497/* File: armv6t2/binopLit16.S */
6498    /*
6499     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6500     * that specifies an instruction that performs "result = r0 op r1".
6501     * This could be an ARM instruction or a function call.  (If the result
6502     * comes back in a register other than r0, you can override "result".)
6503     *
6504     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6505     * vCC (r1).  Useful for integer division and modulus.
6506     *
6507     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6508     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6509     */
6510    /* binop/lit16 vA, vB, #+CCCC */
6511    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6512    mov     r2, rINST, lsr #12          @ r2<- B
6513    ubfx    r9, rINST, #8, #4           @ r9<- A
6514    GET_VREG(r0, r2)                    @ r0<- vB
6515    .if 0
6516    cmp     r1, #0                      @ is second operand zero?
6517    beq     common_errDivideByZero
6518    .endif
6519    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6520
6521    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6522    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6523    SET_VREG(r0, r9)               @ vAA<- r0
6524    GOTO_OPCODE(ip)                     @ jump to next instruction
6525    /* 10-13 instructions */
6526
6527
6528
6529/* ------------------------------ */
6530    .balign 64
6531.L_OP_DIV_INT_LIT16: /* 0xd3 */
6532/* File: armv6t2/OP_DIV_INT_LIT16.S */
6533/* File: armv6t2/binopLit16.S */
6534    /*
6535     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6536     * that specifies an instruction that performs "result = r0 op r1".
6537     * This could be an ARM instruction or a function call.  (If the result
6538     * comes back in a register other than r0, you can override "result".)
6539     *
6540     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6541     * vCC (r1).  Useful for integer division and modulus.
6542     *
6543     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6544     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6545     */
6546    /* binop/lit16 vA, vB, #+CCCC */
6547    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6548    mov     r2, rINST, lsr #12          @ r2<- B
6549    ubfx    r9, rINST, #8, #4           @ r9<- A
6550    GET_VREG(r0, r2)                    @ r0<- vB
6551    .if 1
6552    cmp     r1, #0                      @ is second operand zero?
6553    beq     common_errDivideByZero
6554    .endif
6555    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6556
6557    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6559    SET_VREG(r0, r9)               @ vAA<- r0
6560    GOTO_OPCODE(ip)                     @ jump to next instruction
6561    /* 10-13 instructions */
6562
6563
6564
6565/* ------------------------------ */
6566    .balign 64
6567.L_OP_REM_INT_LIT16: /* 0xd4 */
6568/* File: armv6t2/OP_REM_INT_LIT16.S */
6569/* idivmod returns quotient in r0 and remainder in r1 */
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 1
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    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6596    SET_VREG(r1, r9)               @ vAA<- r1
6597    GOTO_OPCODE(ip)                     @ jump to next instruction
6598    /* 10-13 instructions */
6599
6600
6601
6602/* ------------------------------ */
6603    .balign 64
6604.L_OP_AND_INT_LIT16: /* 0xd5 */
6605/* File: armv6t2/OP_AND_INT_LIT16.S */
6606/* File: armv6t2/binopLit16.S */
6607    /*
6608     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6609     * that specifies an instruction that performs "result = r0 op r1".
6610     * This could be an ARM instruction or a function call.  (If the result
6611     * comes back in a register other than r0, you can override "result".)
6612     *
6613     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6614     * vCC (r1).  Useful for integer division and modulus.
6615     *
6616     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6617     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6618     */
6619    /* binop/lit16 vA, vB, #+CCCC */
6620    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6621    mov     r2, rINST, lsr #12          @ r2<- B
6622    ubfx    r9, rINST, #8, #4           @ r9<- A
6623    GET_VREG(r0, r2)                    @ r0<- vB
6624    .if 0
6625    cmp     r1, #0                      @ is second operand zero?
6626    beq     common_errDivideByZero
6627    .endif
6628    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6629
6630    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6631    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6632    SET_VREG(r0, r9)               @ vAA<- r0
6633    GOTO_OPCODE(ip)                     @ jump to next instruction
6634    /* 10-13 instructions */
6635
6636
6637
6638/* ------------------------------ */
6639    .balign 64
6640.L_OP_OR_INT_LIT16: /* 0xd6 */
6641/* File: armv6t2/OP_OR_INT_LIT16.S */
6642/* File: armv6t2/binopLit16.S */
6643    /*
6644     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6645     * that specifies an instruction that performs "result = r0 op r1".
6646     * This could be an ARM instruction or a function call.  (If the result
6647     * comes back in a register other than r0, you can override "result".)
6648     *
6649     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6650     * vCC (r1).  Useful for integer division and modulus.
6651     *
6652     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6653     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6654     */
6655    /* binop/lit16 vA, vB, #+CCCC */
6656    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6657    mov     r2, rINST, lsr #12          @ r2<- B
6658    ubfx    r9, rINST, #8, #4           @ r9<- A
6659    GET_VREG(r0, r2)                    @ r0<- vB
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    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6668    SET_VREG(r0, r9)               @ vAA<- r0
6669    GOTO_OPCODE(ip)                     @ jump to next instruction
6670    /* 10-13 instructions */
6671
6672
6673
6674/* ------------------------------ */
6675    .balign 64
6676.L_OP_XOR_INT_LIT16: /* 0xd7 */
6677/* File: armv6t2/OP_XOR_INT_LIT16.S */
6678/* File: armv6t2/binopLit16.S */
6679    /*
6680     * Generic 32-bit "lit16" 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/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6689     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6690     */
6691    /* binop/lit16 vA, vB, #+CCCC */
6692    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6693    mov     r2, rINST, lsr #12          @ r2<- B
6694    ubfx    r9, rINST, #8, #4           @ r9<- A
6695    GET_VREG(r0, r2)                    @ r0<- vB
6696    .if 0
6697    cmp     r1, #0                      @ is second operand zero?
6698    beq     common_errDivideByZero
6699    .endif
6700    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6701
6702    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6703    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6704    SET_VREG(r0, r9)               @ vAA<- r0
6705    GOTO_OPCODE(ip)                     @ jump to next instruction
6706    /* 10-13 instructions */
6707
6708
6709
6710/* ------------------------------ */
6711    .balign 64
6712.L_OP_ADD_INT_LIT8: /* 0xd8 */
6713/* File: armv5te/OP_ADD_INT_LIT8.S */
6714/* File: armv5te/binopLit8.S */
6715    /*
6716     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6717     * that specifies an instruction that performs "result = r0 op r1".
6718     * This could be an ARM instruction or a function call.  (If the result
6719     * comes back in a register other than r0, you can override "result".)
6720     *
6721     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6722     * vCC (r1).  Useful for integer division and modulus.
6723     *
6724     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6725     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6726     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6727     */
6728    /* binop/lit8 vAA, vBB, #+CC */
6729    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6730    mov     r9, rINST, lsr #8           @ r9<- AA
6731    and     r2, r3, #255                @ r2<- BB
6732    GET_VREG(r0, r2)                    @ r0<- vBB
6733    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6734    .if 0
6735    @cmp     r1, #0                      @ is second operand zero?
6736    beq     common_errDivideByZero
6737    .endif
6738    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6739
6740                               @ optional op; may set condition codes
6741    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6743    SET_VREG(r0, r9)               @ vAA<- r0
6744    GOTO_OPCODE(ip)                     @ jump to next instruction
6745    /* 10-12 instructions */
6746
6747
6748
6749/* ------------------------------ */
6750    .balign 64
6751.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6752/* File: armv5te/OP_RSUB_INT_LIT8.S */
6753/* File: armv5te/binopLit8.S */
6754    /*
6755     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6756     * that specifies an instruction that performs "result = r0 op r1".
6757     * This could be an ARM instruction or a function call.  (If the result
6758     * comes back in a register other than r0, you can override "result".)
6759     *
6760     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6761     * vCC (r1).  Useful for integer division and modulus.
6762     *
6763     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6764     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6765     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6766     */
6767    /* binop/lit8 vAA, vBB, #+CC */
6768    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6769    mov     r9, rINST, lsr #8           @ r9<- AA
6770    and     r2, r3, #255                @ r2<- BB
6771    GET_VREG(r0, r2)                    @ r0<- vBB
6772    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6773    .if 0
6774    @cmp     r1, #0                      @ is second operand zero?
6775    beq     common_errDivideByZero
6776    .endif
6777    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6778
6779                               @ optional op; may set condition codes
6780    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6781    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6782    SET_VREG(r0, r9)               @ vAA<- r0
6783    GOTO_OPCODE(ip)                     @ jump to next instruction
6784    /* 10-12 instructions */
6785
6786
6787
6788/* ------------------------------ */
6789    .balign 64
6790.L_OP_MUL_INT_LIT8: /* 0xda */
6791/* File: armv5te/OP_MUL_INT_LIT8.S */
6792/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6793/* File: armv5te/binopLit8.S */
6794    /*
6795     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6796     * that specifies an instruction that performs "result = r0 op r1".
6797     * This could be an ARM instruction or a function call.  (If the result
6798     * comes back in a register other than r0, you can override "result".)
6799     *
6800     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6801     * vCC (r1).  Useful for integer division and modulus.
6802     *
6803     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6804     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6805     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6806     */
6807    /* binop/lit8 vAA, vBB, #+CC */
6808    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6809    mov     r9, rINST, lsr #8           @ r9<- AA
6810    and     r2, r3, #255                @ r2<- BB
6811    GET_VREG(r0, r2)                    @ r0<- vBB
6812    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6813    .if 0
6814    @cmp     r1, #0                      @ is second operand zero?
6815    beq     common_errDivideByZero
6816    .endif
6817    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6818
6819                               @ optional op; may set condition codes
6820    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6822    SET_VREG(r0, r9)               @ vAA<- r0
6823    GOTO_OPCODE(ip)                     @ jump to next instruction
6824    /* 10-12 instructions */
6825
6826
6827
6828/* ------------------------------ */
6829    .balign 64
6830.L_OP_DIV_INT_LIT8: /* 0xdb */
6831/* File: armv5te/OP_DIV_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 1
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    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6861    SET_VREG(r0, r9)               @ vAA<- r0
6862    GOTO_OPCODE(ip)                     @ jump to next instruction
6863    /* 10-12 instructions */
6864
6865
6866
6867/* ------------------------------ */
6868    .balign 64
6869.L_OP_REM_INT_LIT8: /* 0xdc */
6870/* File: armv5te/OP_REM_INT_LIT8.S */
6871/* idivmod returns quotient in r0 and remainder in r1 */
6872/* File: armv5te/binopLit8.S */
6873    /*
6874     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6875     * that specifies an instruction that performs "result = r0 op r1".
6876     * This could be an ARM instruction or a function call.  (If the result
6877     * comes back in a register other than r0, you can override "result".)
6878     *
6879     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6880     * vCC (r1).  Useful for integer division and modulus.
6881     *
6882     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6883     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6884     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6885     */
6886    /* binop/lit8 vAA, vBB, #+CC */
6887    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6888    mov     r9, rINST, lsr #8           @ r9<- AA
6889    and     r2, r3, #255                @ r2<- BB
6890    GET_VREG(r0, r2)                    @ r0<- vBB
6891    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6892    .if 1
6893    @cmp     r1, #0                      @ is second operand zero?
6894    beq     common_errDivideByZero
6895    .endif
6896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6897
6898                               @ optional op; may set condition codes
6899    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6901    SET_VREG(r1, r9)               @ vAA<- r1
6902    GOTO_OPCODE(ip)                     @ jump to next instruction
6903    /* 10-12 instructions */
6904
6905
6906
6907/* ------------------------------ */
6908    .balign 64
6909.L_OP_AND_INT_LIT8: /* 0xdd */
6910/* File: armv5te/OP_AND_INT_LIT8.S */
6911/* File: armv5te/binopLit8.S */
6912    /*
6913     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6914     * that specifies an instruction that performs "result = r0 op r1".
6915     * This could be an ARM instruction or a function call.  (If the result
6916     * comes back in a register other than r0, you can override "result".)
6917     *
6918     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6919     * vCC (r1).  Useful for integer division and modulus.
6920     *
6921     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6922     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6923     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6924     */
6925    /* binop/lit8 vAA, vBB, #+CC */
6926    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6927    mov     r9, rINST, lsr #8           @ r9<- AA
6928    and     r2, r3, #255                @ r2<- BB
6929    GET_VREG(r0, r2)                    @ r0<- vBB
6930    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6931    .if 0
6932    @cmp     r1, #0                      @ is second operand zero?
6933    beq     common_errDivideByZero
6934    .endif
6935    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6936
6937                               @ optional op; may set condition codes
6938    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6940    SET_VREG(r0, r9)               @ vAA<- r0
6941    GOTO_OPCODE(ip)                     @ jump to next instruction
6942    /* 10-12 instructions */
6943
6944
6945
6946/* ------------------------------ */
6947    .balign 64
6948.L_OP_OR_INT_LIT8: /* 0xde */
6949/* File: armv5te/OP_OR_INT_LIT8.S */
6950/* File: armv5te/binopLit8.S */
6951    /*
6952     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6953     * that specifies an instruction that performs "result = r0 op r1".
6954     * This could be an ARM instruction or a function call.  (If the result
6955     * comes back in a register other than r0, you can override "result".)
6956     *
6957     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6958     * vCC (r1).  Useful for integer division and modulus.
6959     *
6960     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6961     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6962     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6963     */
6964    /* binop/lit8 vAA, vBB, #+CC */
6965    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6966    mov     r9, rINST, lsr #8           @ r9<- AA
6967    and     r2, r3, #255                @ r2<- BB
6968    GET_VREG(r0, r2)                    @ r0<- vBB
6969    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6970    .if 0
6971    @cmp     r1, #0                      @ is second operand zero?
6972    beq     common_errDivideByZero
6973    .endif
6974    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6975
6976                               @ optional op; may set condition codes
6977    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6978    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6979    SET_VREG(r0, r9)               @ vAA<- r0
6980    GOTO_OPCODE(ip)                     @ jump to next instruction
6981    /* 10-12 instructions */
6982
6983
6984
6985/* ------------------------------ */
6986    .balign 64
6987.L_OP_XOR_INT_LIT8: /* 0xdf */
6988/* File: armv5te/OP_XOR_INT_LIT8.S */
6989/* File: armv5te/binopLit8.S */
6990    /*
6991     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6992     * that specifies an instruction that performs "result = r0 op r1".
6993     * This could be an ARM instruction or a function call.  (If the result
6994     * comes back in a register other than r0, you can override "result".)
6995     *
6996     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6997     * vCC (r1).  Useful for integer division and modulus.
6998     *
6999     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7000     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7001     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7002     */
7003    /* binop/lit8 vAA, vBB, #+CC */
7004    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7005    mov     r9, rINST, lsr #8           @ r9<- AA
7006    and     r2, r3, #255                @ r2<- BB
7007    GET_VREG(r0, r2)                    @ r0<- vBB
7008    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7009    .if 0
7010    @cmp     r1, #0                      @ is second operand zero?
7011    beq     common_errDivideByZero
7012    .endif
7013    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7014
7015                               @ optional op; may set condition codes
7016    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7017    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7018    SET_VREG(r0, r9)               @ vAA<- r0
7019    GOTO_OPCODE(ip)                     @ jump to next instruction
7020    /* 10-12 instructions */
7021
7022
7023
7024/* ------------------------------ */
7025    .balign 64
7026.L_OP_SHL_INT_LIT8: /* 0xe0 */
7027/* File: armv5te/OP_SHL_INT_LIT8.S */
7028/* File: armv5te/binopLit8.S */
7029    /*
7030     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7031     * that specifies an instruction that performs "result = r0 op r1".
7032     * This could be an ARM instruction or a function call.  (If the result
7033     * comes back in a register other than r0, you can override "result".)
7034     *
7035     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7036     * vCC (r1).  Useful for integer division and modulus.
7037     *
7038     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7039     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7040     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7041     */
7042    /* binop/lit8 vAA, vBB, #+CC */
7043    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7044    mov     r9, rINST, lsr #8           @ r9<- AA
7045    and     r2, r3, #255                @ r2<- BB
7046    GET_VREG(r0, r2)                    @ r0<- vBB
7047    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7048    .if 0
7049    @cmp     r1, #0                      @ is second operand zero?
7050    beq     common_errDivideByZero
7051    .endif
7052    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7053
7054    and     r1, r1, #31                           @ optional op; may set condition codes
7055    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7056    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7057    SET_VREG(r0, r9)               @ vAA<- r0
7058    GOTO_OPCODE(ip)                     @ jump to next instruction
7059    /* 10-12 instructions */
7060
7061
7062
7063/* ------------------------------ */
7064    .balign 64
7065.L_OP_SHR_INT_LIT8: /* 0xe1 */
7066/* File: armv5te/OP_SHR_INT_LIT8.S */
7067/* File: armv5te/binopLit8.S */
7068    /*
7069     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7070     * that specifies an instruction that performs "result = r0 op r1".
7071     * This could be an ARM instruction or a function call.  (If the result
7072     * comes back in a register other than r0, you can override "result".)
7073     *
7074     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7075     * vCC (r1).  Useful for integer division and modulus.
7076     *
7077     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7078     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7079     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7080     */
7081    /* binop/lit8 vAA, vBB, #+CC */
7082    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7083    mov     r9, rINST, lsr #8           @ r9<- AA
7084    and     r2, r3, #255                @ r2<- BB
7085    GET_VREG(r0, r2)                    @ r0<- vBB
7086    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7087    .if 0
7088    @cmp     r1, #0                      @ is second operand zero?
7089    beq     common_errDivideByZero
7090    .endif
7091    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7092
7093    and     r1, r1, #31                           @ optional op; may set condition codes
7094    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7095    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7096    SET_VREG(r0, r9)               @ vAA<- r0
7097    GOTO_OPCODE(ip)                     @ jump to next instruction
7098    /* 10-12 instructions */
7099
7100
7101
7102/* ------------------------------ */
7103    .balign 64
7104.L_OP_USHR_INT_LIT8: /* 0xe2 */
7105/* File: armv5te/OP_USHR_INT_LIT8.S */
7106/* File: armv5te/binopLit8.S */
7107    /*
7108     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7109     * that specifies an instruction that performs "result = r0 op r1".
7110     * This could be an ARM instruction or a function call.  (If the result
7111     * comes back in a register other than r0, you can override "result".)
7112     *
7113     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7114     * vCC (r1).  Useful for integer division and modulus.
7115     *
7116     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7117     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7118     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7119     */
7120    /* binop/lit8 vAA, vBB, #+CC */
7121    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7122    mov     r9, rINST, lsr #8           @ r9<- AA
7123    and     r2, r3, #255                @ r2<- BB
7124    GET_VREG(r0, r2)                    @ r0<- vBB
7125    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7126    .if 0
7127    @cmp     r1, #0                      @ is second operand zero?
7128    beq     common_errDivideByZero
7129    .endif
7130    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7131
7132    and     r1, r1, #31                           @ optional op; may set condition codes
7133    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7134    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7135    SET_VREG(r0, r9)               @ vAA<- r0
7136    GOTO_OPCODE(ip)                     @ jump to next instruction
7137    /* 10-12 instructions */
7138
7139
7140
7141/* ------------------------------ */
7142    .balign 64
7143.L_OP_UNUSED_E3: /* 0xe3 */
7144/* File: armv5te/OP_UNUSED_E3.S */
7145/* File: armv5te/unused.S */
7146    bl      common_abort
7147
7148
7149
7150/* ------------------------------ */
7151    .balign 64
7152.L_OP_UNUSED_E4: /* 0xe4 */
7153/* File: armv5te/OP_UNUSED_E4.S */
7154/* File: armv5te/unused.S */
7155    bl      common_abort
7156
7157
7158
7159/* ------------------------------ */
7160    .balign 64
7161.L_OP_UNUSED_E5: /* 0xe5 */
7162/* File: armv5te/OP_UNUSED_E5.S */
7163/* File: armv5te/unused.S */
7164    bl      common_abort
7165
7166
7167
7168/* ------------------------------ */
7169    .balign 64
7170.L_OP_UNUSED_E6: /* 0xe6 */
7171/* File: armv5te/OP_UNUSED_E6.S */
7172/* File: armv5te/unused.S */
7173    bl      common_abort
7174
7175
7176
7177/* ------------------------------ */
7178    .balign 64
7179.L_OP_UNUSED_E7: /* 0xe7 */
7180/* File: armv5te/OP_UNUSED_E7.S */
7181/* File: armv5te/unused.S */
7182    bl      common_abort
7183
7184
7185
7186/* ------------------------------ */
7187    .balign 64
7188.L_OP_UNUSED_E8: /* 0xe8 */
7189/* File: armv5te/OP_UNUSED_E8.S */
7190/* File: armv5te/unused.S */
7191    bl      common_abort
7192
7193
7194
7195/* ------------------------------ */
7196    .balign 64
7197.L_OP_UNUSED_E9: /* 0xe9 */
7198/* File: armv5te/OP_UNUSED_E9.S */
7199/* File: armv5te/unused.S */
7200    bl      common_abort
7201
7202
7203
7204/* ------------------------------ */
7205    .balign 64
7206.L_OP_UNUSED_EA: /* 0xea */
7207/* File: armv5te/OP_UNUSED_EA.S */
7208/* File: armv5te/unused.S */
7209    bl      common_abort
7210
7211
7212
7213/* ------------------------------ */
7214    .balign 64
7215.L_OP_UNUSED_EB: /* 0xeb */
7216/* File: armv5te/OP_UNUSED_EB.S */
7217/* File: armv5te/unused.S */
7218    bl      common_abort
7219
7220
7221
7222/* ------------------------------ */
7223    .balign 64
7224.L_OP_UNUSED_EC: /* 0xec */
7225/* File: armv5te/OP_UNUSED_EC.S */
7226/* File: armv5te/unused.S */
7227    bl      common_abort
7228
7229
7230
7231/* ------------------------------ */
7232    .balign 64
7233.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7234/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7235    /*
7236     * Handle a throw-verification-error instruction.  This throws an
7237     * exception for an error discovered during verification.  The
7238     * exception is indicated by AA, with some detail provided by BBBB.
7239     */
7240    /* op AA, ref@BBBB */
7241    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7242    FETCH(r2, 1)                        @ r2<- BBBB
7243    EXPORT_PC()                         @ export the PC
7244    mov     r1, rINST, lsr #8           @ r1<- AA
7245    bl      dvmThrowVerificationError   @ always throws
7246    b       common_exceptionThrown      @ handle exception
7247
7248
7249/* ------------------------------ */
7250    .balign 64
7251.L_OP_EXECUTE_INLINE: /* 0xee */
7252/* File: armv5te/OP_EXECUTE_INLINE.S */
7253    /*
7254     * Execute a "native inline" instruction.
7255     *
7256     * We need to call:
7257     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7258     *
7259     * The first four args are in r0-r3, but the last two must be pushed
7260     * onto the stack.
7261     */
7262    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7263    FETCH(r10, 1)                       @ r10<- BBBB
7264    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7265    EXPORT_PC()                         @ can throw
7266    sub     sp, sp, #8                  @ make room for arg(s)
7267    mov     r0, rINST, lsr #12          @ r0<- B
7268    str     r1, [sp]                    @ push &glue->retval
7269    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7270    add     sp, sp, #8                  @ pop stack
7271    cmp     r0, #0                      @ test boolean result of inline
7272    beq     common_exceptionThrown      @ returned false, handle exception
7273    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7274    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7275    GOTO_OPCODE(ip)                     @ jump to next instruction
7276
7277/* ------------------------------ */
7278    .balign 64
7279.L_OP_UNUSED_EF: /* 0xef */
7280/* File: armv5te/OP_UNUSED_EF.S */
7281/* File: armv5te/unused.S */
7282    bl      common_abort
7283
7284
7285
7286/* ------------------------------ */
7287    .balign 64
7288.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7289/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7290    /*
7291     * invoke-direct-empty is a no-op in a "standard" interpreter.
7292     */
7293    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7294    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7295    GOTO_OPCODE(ip)                     @ execute it
7296
7297/* ------------------------------ */
7298    .balign 64
7299.L_OP_UNUSED_F1: /* 0xf1 */
7300/* File: armv5te/OP_UNUSED_F1.S */
7301/* File: armv5te/unused.S */
7302    bl      common_abort
7303
7304
7305
7306/* ------------------------------ */
7307    .balign 64
7308.L_OP_IGET_QUICK: /* 0xf2 */
7309/* File: armv6t2/OP_IGET_QUICK.S */
7310    /* For: iget-quick, iget-object-quick */
7311    /* op vA, vB, offset@CCCC */
7312    mov     r2, rINST, lsr #12          @ r2<- B
7313    FETCH(r1, 1)                        @ r1<- field byte offset
7314    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7315    ubfx    r2, rINST, #8, #4           @ r2<- A
7316    cmp     r3, #0                      @ check object for null
7317    beq     common_errNullObject        @ object was null
7318    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7319    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7320    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7321    SET_VREG(r0, r2)                    @ fp[A]<- r0
7322    GOTO_OPCODE(ip)                     @ jump to next instruction
7323
7324
7325/* ------------------------------ */
7326    .balign 64
7327.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7328/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7329    /* iget-wide-quick vA, vB, offset@CCCC */
7330    mov     r2, rINST, lsr #12          @ r2<- B
7331    FETCH(r1, 1)                        @ r1<- field byte offset
7332    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7333    ubfx    r2, rINST, #8, #4           @ r2<- A
7334    cmp     r3, #0                      @ check object for null
7335    beq     common_errNullObject        @ object was null
7336    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7337    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7338    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7340    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7341    GOTO_OPCODE(ip)                     @ jump to next instruction
7342
7343
7344/* ------------------------------ */
7345    .balign 64
7346.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7347/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7348/* File: armv5te/OP_IGET_QUICK.S */
7349    /* For: iget-quick, iget-object-quick */
7350    /* op vA, vB, offset@CCCC */
7351    mov     r2, rINST, lsr #12          @ r2<- B
7352    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7353    FETCH(r1, 1)                        @ r1<- field byte offset
7354    cmp     r3, #0                      @ check object for null
7355    mov     r2, rINST, lsr #8           @ r2<- A(+)
7356    beq     common_errNullObject        @ object was null
7357    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7358    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7359    and     r2, r2, #15
7360    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7361    SET_VREG(r0, r2)                    @ fp[A]<- r0
7362    GOTO_OPCODE(ip)                     @ jump to next instruction
7363
7364
7365
7366/* ------------------------------ */
7367    .balign 64
7368.L_OP_IPUT_QUICK: /* 0xf5 */
7369/* File: armv6t2/OP_IPUT_QUICK.S */
7370    /* For: iput-quick, iput-object-quick */
7371    /* op vA, vB, offset@CCCC */
7372    mov     r2, rINST, lsr #12          @ r2<- B
7373    FETCH(r1, 1)                        @ r1<- field byte offset
7374    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7375    ubfx    r2, rINST, #8, #4           @ r2<- A
7376    cmp     r3, #0                      @ check object for null
7377    beq     common_errNullObject        @ object was null
7378    GET_VREG(r0, r2)                    @ r0<- fp[A]
7379    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7380    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7381    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7382    GOTO_OPCODE(ip)                     @ jump to next instruction
7383
7384
7385/* ------------------------------ */
7386    .balign 64
7387.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7388/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7389    /* iput-wide-quick vA, vB, offset@CCCC */
7390    mov     r1, rINST, lsr #12          @ r1<- B
7391    ubfx    r0, rINST, #8, #4           @ r0<- A
7392    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7393    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7394    cmp     r2, #0                      @ check object for null
7395    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7396    beq     common_errNullObject        @ object was null
7397    FETCH(r3, 1)                        @ r3<- field byte offset
7398    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7399    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7400    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7401    GOTO_OPCODE(ip)                     @ jump to next instruction
7402
7403
7404/* ------------------------------ */
7405    .balign 64
7406.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7407/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7408/* File: armv5te/OP_IPUT_QUICK.S */
7409    /* For: iput-quick, iput-object-quick */
7410    /* op vA, vB, offset@CCCC */
7411    mov     r2, rINST, lsr #12          @ r2<- B
7412    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7413    FETCH(r1, 1)                        @ r1<- field byte offset
7414    cmp     r3, #0                      @ check object for null
7415    mov     r2, rINST, lsr #8           @ r2<- A(+)
7416    beq     common_errNullObject        @ object was null
7417    and     r2, r2, #15
7418    GET_VREG(r0, r2)                    @ r0<- fp[A]
7419    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7420    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7421    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7422    GOTO_OPCODE(ip)                     @ jump to next instruction
7423
7424
7425
7426/* ------------------------------ */
7427    .balign 64
7428.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7429/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7430    /*
7431     * Handle an optimized virtual method call.
7432     *
7433     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7434     */
7435    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7436    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7437    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7438    FETCH(r1, 1)                        @ r1<- BBBB
7439    .if     (!0)
7440    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7441    .endif
7442    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7443    cmp     r2, #0                      @ is "this" null?
7444    beq     common_errNullObject        @ null "this", throw exception
7445    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7446    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7447    EXPORT_PC()                         @ invoke must export
7448    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7449    bl      common_invokeMethodNoRange @ continue on
7450
7451/* ------------------------------ */
7452    .balign 64
7453.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7454/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7455/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7456    /*
7457     * Handle an optimized virtual method call.
7458     *
7459     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7460     */
7461    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7462    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7463    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7464    FETCH(r1, 1)                        @ r1<- BBBB
7465    .if     (!1)
7466    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7467    .endif
7468    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7469    cmp     r2, #0                      @ is "this" null?
7470    beq     common_errNullObject        @ null "this", throw exception
7471    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7472    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7473    EXPORT_PC()                         @ invoke must export
7474    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7475    bl      common_invokeMethodRange @ continue on
7476
7477
7478/* ------------------------------ */
7479    .balign 64
7480.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7481/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7482    /*
7483     * Handle an optimized "super" method call.
7484     *
7485     * for: [opt] invoke-super-quick, invoke-super-quick/range
7486     */
7487    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7488    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7489    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7490    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7491    .if     (!0)
7492    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7493    .endif
7494    FETCH(r1, 1)                        @ r1<- BBBB
7495    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7496    EXPORT_PC()                         @ must export for invoke
7497    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7498    GET_VREG(r3, r10)                   @ r3<- "this"
7499    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7500    cmp     r3, #0                      @ null "this" ref?
7501    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7502    beq     common_errNullObject        @ "this" is null, throw exception
7503    bl      common_invokeMethodNoRange @ continue on
7504
7505
7506/* ------------------------------ */
7507    .balign 64
7508.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7509/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7510/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7511    /*
7512     * Handle an optimized "super" method call.
7513     *
7514     * for: [opt] invoke-super-quick, invoke-super-quick/range
7515     */
7516    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7517    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7518    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7519    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7520    .if     (!1)
7521    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7522    .endif
7523    FETCH(r1, 1)                        @ r1<- BBBB
7524    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7525    EXPORT_PC()                         @ must export for invoke
7526    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7527    GET_VREG(r3, r10)                   @ r3<- "this"
7528    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7529    cmp     r3, #0                      @ null "this" ref?
7530    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7531    beq     common_errNullObject        @ "this" is null, throw exception
7532    bl      common_invokeMethodRange @ continue on
7533
7534
7535
7536/* ------------------------------ */
7537    .balign 64
7538.L_OP_UNUSED_FC: /* 0xfc */
7539/* File: armv5te/OP_UNUSED_FC.S */
7540/* File: armv5te/unused.S */
7541    bl      common_abort
7542
7543
7544
7545/* ------------------------------ */
7546    .balign 64
7547.L_OP_UNUSED_FD: /* 0xfd */
7548/* File: armv5te/OP_UNUSED_FD.S */
7549/* File: armv5te/unused.S */
7550    bl      common_abort
7551
7552
7553
7554/* ------------------------------ */
7555    .balign 64
7556.L_OP_UNUSED_FE: /* 0xfe */
7557/* File: armv5te/OP_UNUSED_FE.S */
7558/* File: armv5te/unused.S */
7559    bl      common_abort
7560
7561
7562
7563/* ------------------------------ */
7564    .balign 64
7565.L_OP_UNUSED_FF: /* 0xff */
7566/* File: armv5te/OP_UNUSED_FF.S */
7567/* File: armv5te/unused.S */
7568    bl      common_abort
7569
7570
7571
7572
7573    .balign 64
7574    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7575    .global dvmAsmInstructionEnd
7576dvmAsmInstructionEnd:
7577
7578/*
7579 * ===========================================================================
7580 *  Sister implementations
7581 * ===========================================================================
7582 */
7583    .global dvmAsmSisterStart
7584    .type   dvmAsmSisterStart, %function
7585    .text
7586    .balign 4
7587dvmAsmSisterStart:
7588
7589/* continuation for OP_CONST_STRING */
7590
7591    /*
7592     * Continuation if the String has not yet been resolved.
7593     *  r1: BBBB (String ref)
7594     *  r9: target register
7595     */
7596.LOP_CONST_STRING_resolve:
7597    EXPORT_PC()
7598    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7599    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7600    bl      dvmResolveString            @ r0<- String reference
7601    cmp     r0, #0                      @ failed?
7602    beq     common_exceptionThrown      @ yup, handle the exception
7603    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7604    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7605    SET_VREG(r0, r9)                    @ vAA<- r0
7606    GOTO_OPCODE(ip)                     @ jump to next instruction
7607
7608
7609/* continuation for OP_CONST_STRING_JUMBO */
7610
7611    /*
7612     * Continuation if the String has not yet been resolved.
7613     *  r1: BBBBBBBB (String ref)
7614     *  r9: target register
7615     */
7616.LOP_CONST_STRING_JUMBO_resolve:
7617    EXPORT_PC()
7618    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7619    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7620    bl      dvmResolveString            @ r0<- String reference
7621    cmp     r0, #0                      @ failed?
7622    beq     common_exceptionThrown      @ yup, handle the exception
7623    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7625    SET_VREG(r0, r9)                    @ vAA<- r0
7626    GOTO_OPCODE(ip)                     @ jump to next instruction
7627
7628
7629/* continuation for OP_CONST_CLASS */
7630
7631    /*
7632     * Continuation if the Class has not yet been resolved.
7633     *  r1: BBBB (Class ref)
7634     *  r9: target register
7635     */
7636.LOP_CONST_CLASS_resolve:
7637    EXPORT_PC()
7638    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7639    mov     r2, #1                      @ r2<- true
7640    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7641    bl      dvmResolveClass             @ r0<- Class reference
7642    cmp     r0, #0                      @ failed?
7643    beq     common_exceptionThrown      @ yup, handle the exception
7644    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7645    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7646    SET_VREG(r0, r9)                    @ vAA<- r0
7647    GOTO_OPCODE(ip)                     @ jump to next instruction
7648
7649
7650/* continuation for OP_CHECK_CAST */
7651
7652    /*
7653     * Trivial test failed, need to perform full check.  This is common.
7654     *  r0 holds obj->clazz
7655     *  r1 holds class resolved from BBBB
7656     *  r9 holds object
7657     */
7658.LOP_CHECK_CAST_fullcheck:
7659    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7660    cmp     r0, #0                      @ failed?
7661    bne     .LOP_CHECK_CAST_okay            @ no, success
7662
7663    @ A cast has failed.  We need to throw a ClassCastException with the
7664    @ class of the object that failed to be cast.
7665    EXPORT_PC()                         @ about to throw
7666    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7667    ldr     r0, .LstrClassCastExceptionPtr
7668    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7669    bl      dvmThrowExceptionWithClassMessage
7670    b       common_exceptionThrown
7671
7672    /*
7673     * Resolution required.  This is the least-likely path.
7674     *
7675     *  r2 holds BBBB
7676     *  r9 holds object
7677     */
7678.LOP_CHECK_CAST_resolve:
7679    EXPORT_PC()                         @ resolve() could throw
7680    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7681    mov     r1, r2                      @ r1<- BBBB
7682    mov     r2, #0                      @ r2<- false
7683    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7684    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7685    cmp     r0, #0                      @ got null?
7686    beq     common_exceptionThrown      @ yes, handle exception
7687    mov     r1, r0                      @ r1<- class resolved from BBB
7688    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7689    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7690
7691.LstrClassCastExceptionPtr:
7692    .word   .LstrClassCastException
7693
7694
7695/* continuation for OP_INSTANCE_OF */
7696
7697    /*
7698     * Trivial test failed, need to perform full check.  This is common.
7699     *  r0 holds obj->clazz
7700     *  r1 holds class resolved from BBBB
7701     *  r9 holds A
7702     */
7703.LOP_INSTANCE_OF_fullcheck:
7704    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7705    @ fall through to OP_INSTANCE_OF_store
7706
7707    /*
7708     * r0 holds boolean result
7709     * r9 holds A
7710     */
7711.LOP_INSTANCE_OF_store:
7712    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7713    SET_VREG(r0, r9)                    @ vA<- r0
7714    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7715    GOTO_OPCODE(ip)                     @ jump to next instruction
7716
7717    /*
7718     * Trivial test succeeded, save and bail.
7719     *  r9 holds A
7720     */
7721.LOP_INSTANCE_OF_trivial:
7722    mov     r0, #1                      @ indicate success
7723    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7724    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7725    SET_VREG(r0, r9)                    @ vA<- r0
7726    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7727    GOTO_OPCODE(ip)                     @ jump to next instruction
7728
7729    /*
7730     * Resolution required.  This is the least-likely path.
7731     *
7732     *  r3 holds BBBB
7733     *  r9 holds A
7734     */
7735.LOP_INSTANCE_OF_resolve:
7736    EXPORT_PC()                         @ resolve() could throw
7737    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7738    mov     r1, r3                      @ r1<- BBBB
7739    mov     r2, #1                      @ r2<- true
7740    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7741    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7742    cmp     r0, #0                      @ got null?
7743    beq     common_exceptionThrown      @ yes, handle exception
7744    mov     r1, r0                      @ r1<- class resolved from BBB
7745    mov     r3, rINST, lsr #12          @ r3<- B
7746    GET_VREG(r0, r3)                    @ r0<- vB (object)
7747    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7748    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7749
7750
7751/* continuation for OP_NEW_INSTANCE */
7752
7753    .balign 32                          @ minimize cache lines
7754.LOP_NEW_INSTANCE_finish: @ r0=new object
7755    mov     r3, rINST, lsr #8           @ r3<- AA
7756    cmp     r0, #0                      @ failed?
7757    beq     common_exceptionThrown      @ yes, handle the exception
7758    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7760    SET_VREG(r0, r3)                    @ vAA<- r0
7761    GOTO_OPCODE(ip)                     @ jump to next instruction
7762
7763    /*
7764     * Class initialization required.
7765     *
7766     *  r0 holds class object
7767     */
7768.LOP_NEW_INSTANCE_needinit:
7769    mov     r9, r0                      @ save r0
7770    bl      dvmInitClass                @ initialize class
7771    cmp     r0, #0                      @ check boolean result
7772    mov     r0, r9                      @ restore r0
7773    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7774    b       common_exceptionThrown      @ failed, deal with init exception
7775
7776    /*
7777     * Resolution required.  This is the least-likely path.
7778     *
7779     *  r1 holds BBBB
7780     */
7781.LOP_NEW_INSTANCE_resolve:
7782    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7783    mov     r2, #0                      @ r2<- false
7784    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7785    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7786    cmp     r0, #0                      @ got null?
7787    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7788    b       common_exceptionThrown      @ yes, handle exception
7789
7790.LstrInstantiationErrorPtr:
7791    .word   .LstrInstantiationError
7792
7793
7794/* continuation for OP_NEW_ARRAY */
7795
7796
7797    /*
7798     * Resolve class.  (This is an uncommon case.)
7799     *
7800     *  r1 holds array length
7801     *  r2 holds class ref CCCC
7802     */
7803.LOP_NEW_ARRAY_resolve:
7804    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7805    mov     r9, r1                      @ r9<- length (save)
7806    mov     r1, r2                      @ r1<- CCCC
7807    mov     r2, #0                      @ r2<- false
7808    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7809    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7810    cmp     r0, #0                      @ got null?
7811    mov     r1, r9                      @ r1<- length (restore)
7812    beq     common_exceptionThrown      @ yes, handle exception
7813    @ fall through to OP_NEW_ARRAY_finish
7814
7815    /*
7816     * Finish allocation.
7817     *
7818     *  r0 holds class
7819     *  r1 holds array length
7820     */
7821.LOP_NEW_ARRAY_finish:
7822    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7823    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7824    cmp     r0, #0                      @ failed?
7825    mov     r2, rINST, lsr #8           @ r2<- A+
7826    beq     common_exceptionThrown      @ yes, handle the exception
7827    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7828    and     r2, r2, #15                 @ r2<- A
7829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7830    SET_VREG(r0, r2)                    @ vA<- r0
7831    GOTO_OPCODE(ip)                     @ jump to next instruction
7832
7833
7834/* continuation for OP_FILLED_NEW_ARRAY */
7835
7836    /*
7837     * On entry:
7838     *  r0 holds array class
7839     *  r10 holds AA or BA
7840     */
7841.LOP_FILLED_NEW_ARRAY_continue:
7842    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7843    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7844    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7845    .if     0
7846    mov     r1, r10                     @ r1<- AA (length)
7847    .else
7848    mov     r1, r10, lsr #4             @ r1<- B (length)
7849    .endif
7850    cmp     r3, #'I'                    @ array of ints?
7851    cmpne   r3, #'L'                    @ array of objects?
7852    cmpne   r3, #'['                    @ array of arrays?
7853    mov     r9, r1                      @ save length in r9
7854    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7855    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7856    cmp     r0, #0                      @ null return?
7857    beq     common_exceptionThrown      @ alloc failed, handle exception
7858
7859    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7860    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7861    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7862    subs    r9, r9, #1                  @ length--, check for neg
7863    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7864    bmi     2f                          @ was zero, bail
7865
7866    @ copy values from registers into the array
7867    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7868    .if     0
7869    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
78701:  ldr     r3, [r2], #4                @ r3<- *r2++
7871    subs    r9, r9, #1                  @ count--
7872    str     r3, [r0], #4                @ *contents++ = vX
7873    bpl     1b
7874    @ continue at 2
7875    .else
7876    cmp     r9, #4                      @ length was initially 5?
7877    and     r2, r10, #15                @ r2<- A
7878    bne     1f                          @ <= 4 args, branch
7879    GET_VREG(r3, r2)                    @ r3<- vA
7880    sub     r9, r9, #1                  @ count--
7881    str     r3, [r0, #16]               @ contents[4] = vA
78821:  and     r2, r1, #15                 @ r2<- F/E/D/C
7883    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7884    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7885    subs    r9, r9, #1                  @ count--
7886    str     r3, [r0], #4                @ *contents++ = vX
7887    bpl     1b
7888    @ continue at 2
7889    .endif
7890
78912:
7892    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7893    GOTO_OPCODE(ip)                     @ execute it
7894
7895    /*
7896     * Throw an exception indicating that we have not implemented this
7897     * mode of filled-new-array.
7898     */
7899.LOP_FILLED_NEW_ARRAY_notimpl:
7900    ldr     r0, .L_strInternalError
7901    ldr     r1, .L_strFilledNewArrayNotImpl
7902    bl      dvmThrowException
7903    b       common_exceptionThrown
7904
7905    .if     (!0)                 @ define in one or the other, not both
7906.L_strFilledNewArrayNotImpl:
7907    .word   .LstrFilledNewArrayNotImpl
7908.L_strInternalError:
7909    .word   .LstrInternalError
7910    .endif
7911
7912
7913/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7914
7915    /*
7916     * On entry:
7917     *  r0 holds array class
7918     *  r10 holds AA or BA
7919     */
7920.LOP_FILLED_NEW_ARRAY_RANGE_continue:
7921    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7922    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7923    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7924    .if     1
7925    mov     r1, r10                     @ r1<- AA (length)
7926    .else
7927    mov     r1, r10, lsr #4             @ r1<- B (length)
7928    .endif
7929    cmp     r3, #'I'                    @ array of ints?
7930    cmpne   r3, #'L'                    @ array of objects?
7931    cmpne   r3, #'['                    @ array of arrays?
7932    mov     r9, r1                      @ save length in r9
7933    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7934    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7935    cmp     r0, #0                      @ null return?
7936    beq     common_exceptionThrown      @ alloc failed, handle exception
7937
7938    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7939    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7940    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7941    subs    r9, r9, #1                  @ length--, check for neg
7942    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7943    bmi     2f                          @ was zero, bail
7944
7945    @ copy values from registers into the array
7946    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7947    .if     1
7948    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79491:  ldr     r3, [r2], #4                @ r3<- *r2++
7950    subs    r9, r9, #1                  @ count--
7951    str     r3, [r0], #4                @ *contents++ = vX
7952    bpl     1b
7953    @ continue at 2
7954    .else
7955    cmp     r9, #4                      @ length was initially 5?
7956    and     r2, r10, #15                @ r2<- A
7957    bne     1f                          @ <= 4 args, branch
7958    GET_VREG(r3, r2)                    @ r3<- vA
7959    sub     r9, r9, #1                  @ count--
7960    str     r3, [r0, #16]               @ contents[4] = vA
79611:  and     r2, r1, #15                 @ r2<- F/E/D/C
7962    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7963    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7964    subs    r9, r9, #1                  @ count--
7965    str     r3, [r0], #4                @ *contents++ = vX
7966    bpl     1b
7967    @ continue at 2
7968    .endif
7969
79702:
7971    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7972    GOTO_OPCODE(ip)                     @ execute it
7973
7974    /*
7975     * Throw an exception indicating that we have not implemented this
7976     * mode of filled-new-array.
7977     */
7978.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
7979    ldr     r0, .L_strInternalError
7980    ldr     r1, .L_strFilledNewArrayNotImpl
7981    bl      dvmThrowException
7982    b       common_exceptionThrown
7983
7984    .if     (!1)                 @ define in one or the other, not both
7985.L_strFilledNewArrayNotImpl:
7986    .word   .LstrFilledNewArrayNotImpl
7987.L_strInternalError:
7988    .word   .LstrInternalError
7989    .endif
7990
7991
7992/* continuation for OP_CMPL_FLOAT */
7993.LOP_CMPL_FLOAT_finish:
7994    SET_VREG(r0, r9)                    @ vAA<- r0
7995    GOTO_OPCODE(ip)                     @ jump to next instruction
7996
7997
7998/* continuation for OP_CMPG_FLOAT */
7999.LOP_CMPG_FLOAT_finish:
8000    SET_VREG(r0, r9)                    @ vAA<- r0
8001    GOTO_OPCODE(ip)                     @ jump to next instruction
8002
8003
8004/* continuation for OP_CMPL_DOUBLE */
8005.LOP_CMPL_DOUBLE_finish:
8006    SET_VREG(r0, r9)                    @ vAA<- r0
8007    GOTO_OPCODE(ip)                     @ jump to next instruction
8008
8009
8010/* continuation for OP_CMPG_DOUBLE */
8011.LOP_CMPG_DOUBLE_finish:
8012    SET_VREG(r0, r9)                    @ vAA<- r0
8013    GOTO_OPCODE(ip)                     @ jump to next instruction
8014
8015
8016/* continuation for OP_CMP_LONG */
8017
8018.LOP_CMP_LONG_less:
8019    mvn     r1, #0                      @ r1<- -1
8020    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8021    @ instead, we just replicate the tail end.
8022    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8023    SET_VREG(r1, r9)                    @ vAA<- r1
8024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8025    GOTO_OPCODE(ip)                     @ jump to next instruction
8026
8027.LOP_CMP_LONG_greater:
8028    mov     r1, #1                      @ r1<- 1
8029    @ fall through to _finish
8030
8031.LOP_CMP_LONG_finish:
8032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8033    SET_VREG(r1, r9)                    @ vAA<- r1
8034    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8035    GOTO_OPCODE(ip)                     @ jump to next instruction
8036
8037
8038/* continuation for OP_AGET_WIDE */
8039
8040.LOP_AGET_WIDE_finish:
8041    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8042    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8043    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8044    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8045    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8046    GOTO_OPCODE(ip)                     @ jump to next instruction
8047
8048
8049/* continuation for OP_APUT_WIDE */
8050
8051.LOP_APUT_WIDE_finish:
8052    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8053    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8054    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8055    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8056    GOTO_OPCODE(ip)                     @ jump to next instruction
8057
8058
8059/* continuation for OP_APUT_OBJECT */
8060    /*
8061     * On entry:
8062     *  r1 = vBB (arrayObj)
8063     *  r9 = vAA (obj)
8064     *  r10 = offset into array (vBB + vCC * width)
8065     */
8066.LOP_APUT_OBJECT_finish:
8067    cmp     r9, #0                      @ storing null reference?
8068    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8069    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8070    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8071    bl      dvmCanPutArrayElement       @ test object type vs. array type
8072    cmp     r0, #0                      @ okay?
8073    beq     common_errArrayStore        @ no
8074.LOP_APUT_OBJECT_skip_check:
8075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8076    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8077    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8078    GOTO_OPCODE(ip)                     @ jump to next instruction
8079
8080
8081/* continuation for OP_IGET */
8082
8083    /*
8084     * Currently:
8085     *  r0 holds resolved field
8086     *  r9 holds object
8087     */
8088.LOP_IGET_finish:
8089    @bl      common_squeak0
8090    cmp     r9, #0                      @ check object for null
8091    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8092    beq     common_errNullObject        @ object was null
8093    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8094    ubfx    r2, rINST, #8, #4           @ r2<- A
8095    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8096    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8097    SET_VREG(r0, r2)                    @ fp[A]<- r0
8098    GOTO_OPCODE(ip)                     @ jump to next instruction
8099
8100
8101/* continuation for OP_IGET_WIDE */
8102
8103    /*
8104     * Currently:
8105     *  r0 holds resolved field
8106     *  r9 holds object
8107     */
8108.LOP_IGET_WIDE_finish:
8109    cmp     r9, #0                      @ check object for null
8110    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8111    beq     common_errNullObject        @ object was null
8112    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8113    ubfx    r2, rINST, #8, #4           @ r2<- A
8114    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8115    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8117    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8118    GOTO_OPCODE(ip)                     @ jump to next instruction
8119
8120
8121/* continuation for OP_IGET_OBJECT */
8122
8123    /*
8124     * Currently:
8125     *  r0 holds resolved field
8126     *  r9 holds object
8127     */
8128.LOP_IGET_OBJECT_finish:
8129    @bl      common_squeak0
8130    cmp     r9, #0                      @ check object for null
8131    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8132    beq     common_errNullObject        @ object was null
8133    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8134    mov     r2, rINST, lsr #8           @ r2<- A+
8135    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8136    and     r2, r2, #15                 @ r2<- A
8137    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8138    SET_VREG(r0, r2)                    @ fp[A]<- r0
8139    GOTO_OPCODE(ip)                     @ jump to next instruction
8140
8141
8142/* continuation for OP_IGET_BOOLEAN */
8143
8144    /*
8145     * Currently:
8146     *  r0 holds resolved field
8147     *  r9 holds object
8148     */
8149.LOP_IGET_BOOLEAN_finish:
8150    @bl      common_squeak1
8151    cmp     r9, #0                      @ check object for null
8152    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8153    beq     common_errNullObject        @ object was null
8154    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8155    mov     r2, rINST, lsr #8           @ r2<- A+
8156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8157    and     r2, r2, #15                 @ r2<- A
8158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8159    SET_VREG(r0, r2)                    @ fp[A]<- r0
8160    GOTO_OPCODE(ip)                     @ jump to next instruction
8161
8162
8163/* continuation for OP_IGET_BYTE */
8164
8165    /*
8166     * Currently:
8167     *  r0 holds resolved field
8168     *  r9 holds object
8169     */
8170.LOP_IGET_BYTE_finish:
8171    @bl      common_squeak2
8172    cmp     r9, #0                      @ check object for null
8173    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8174    beq     common_errNullObject        @ object was null
8175    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8176    mov     r2, rINST, lsr #8           @ r2<- A+
8177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8178    and     r2, r2, #15                 @ r2<- A
8179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8180    SET_VREG(r0, r2)                    @ fp[A]<- r0
8181    GOTO_OPCODE(ip)                     @ jump to next instruction
8182
8183
8184/* continuation for OP_IGET_CHAR */
8185
8186    /*
8187     * Currently:
8188     *  r0 holds resolved field
8189     *  r9 holds object
8190     */
8191.LOP_IGET_CHAR_finish:
8192    @bl      common_squeak3
8193    cmp     r9, #0                      @ check object for null
8194    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8195    beq     common_errNullObject        @ object was null
8196    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8197    mov     r2, rINST, lsr #8           @ r2<- A+
8198    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8199    and     r2, r2, #15                 @ r2<- A
8200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8201    SET_VREG(r0, r2)                    @ fp[A]<- r0
8202    GOTO_OPCODE(ip)                     @ jump to next instruction
8203
8204
8205/* continuation for OP_IGET_SHORT */
8206
8207    /*
8208     * Currently:
8209     *  r0 holds resolved field
8210     *  r9 holds object
8211     */
8212.LOP_IGET_SHORT_finish:
8213    @bl      common_squeak4
8214    cmp     r9, #0                      @ check object for null
8215    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8216    beq     common_errNullObject        @ object was null
8217    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8218    mov     r2, rINST, lsr #8           @ r2<- A+
8219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8220    and     r2, r2, #15                 @ r2<- A
8221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8222    SET_VREG(r0, r2)                    @ fp[A]<- r0
8223    GOTO_OPCODE(ip)                     @ jump to next instruction
8224
8225
8226/* continuation for OP_IPUT */
8227
8228    /*
8229     * Currently:
8230     *  r0 holds resolved field
8231     *  r9 holds object
8232     */
8233.LOP_IPUT_finish:
8234    @bl      common_squeak0
8235    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8236    ubfx    r1, rINST, #8, #4           @ r1<- A
8237    cmp     r9, #0                      @ check object for null
8238    GET_VREG(r0, r1)                    @ r0<- fp[A]
8239    beq     common_errNullObject        @ object was null
8240    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8241    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8242    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8243    GOTO_OPCODE(ip)                     @ jump to next instruction
8244
8245
8246/* continuation for OP_IPUT_WIDE */
8247
8248    /*
8249     * Currently:
8250     *  r0 holds resolved field
8251     *  r9 holds object
8252     */
8253.LOP_IPUT_WIDE_finish:
8254    ubfx    r2, rINST, #8, #4           @ r2<- A
8255    cmp     r9, #0                      @ check object for null
8256    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8257    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8258    beq     common_errNullObject        @ object was null
8259    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8260    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8261    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8262    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8263    GOTO_OPCODE(ip)                     @ jump to next instruction
8264
8265
8266/* continuation for OP_IPUT_OBJECT */
8267
8268    /*
8269     * Currently:
8270     *  r0 holds resolved field
8271     *  r9 holds object
8272     */
8273.LOP_IPUT_OBJECT_finish:
8274    @bl      common_squeak0
8275    mov     r1, rINST, lsr #8           @ r1<- A+
8276    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8277    and     r1, r1, #15                 @ r1<- A
8278    cmp     r9, #0                      @ check object for null
8279    GET_VREG(r0, r1)                    @ r0<- fp[A]
8280    beq     common_errNullObject        @ object was null
8281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8282    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8283    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8284    GOTO_OPCODE(ip)                     @ jump to next instruction
8285
8286
8287/* continuation for OP_IPUT_BOOLEAN */
8288
8289    /*
8290     * Currently:
8291     *  r0 holds resolved field
8292     *  r9 holds object
8293     */
8294.LOP_IPUT_BOOLEAN_finish:
8295    @bl      common_squeak1
8296    mov     r1, rINST, lsr #8           @ r1<- A+
8297    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8298    and     r1, r1, #15                 @ r1<- A
8299    cmp     r9, #0                      @ check object for null
8300    GET_VREG(r0, r1)                    @ r0<- fp[A]
8301    beq     common_errNullObject        @ object was null
8302    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8304    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8305    GOTO_OPCODE(ip)                     @ jump to next instruction
8306
8307
8308/* continuation for OP_IPUT_BYTE */
8309
8310    /*
8311     * Currently:
8312     *  r0 holds resolved field
8313     *  r9 holds object
8314     */
8315.LOP_IPUT_BYTE_finish:
8316    @bl      common_squeak2
8317    mov     r1, rINST, lsr #8           @ r1<- A+
8318    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8319    and     r1, r1, #15                 @ r1<- A
8320    cmp     r9, #0                      @ check object for null
8321    GET_VREG(r0, r1)                    @ r0<- fp[A]
8322    beq     common_errNullObject        @ object was null
8323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8325    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8326    GOTO_OPCODE(ip)                     @ jump to next instruction
8327
8328
8329/* continuation for OP_IPUT_CHAR */
8330
8331    /*
8332     * Currently:
8333     *  r0 holds resolved field
8334     *  r9 holds object
8335     */
8336.LOP_IPUT_CHAR_finish:
8337    @bl      common_squeak3
8338    mov     r1, rINST, lsr #8           @ r1<- A+
8339    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8340    and     r1, r1, #15                 @ r1<- A
8341    cmp     r9, #0                      @ check object for null
8342    GET_VREG(r0, r1)                    @ r0<- fp[A]
8343    beq     common_errNullObject        @ object was null
8344    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8346    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8347    GOTO_OPCODE(ip)                     @ jump to next instruction
8348
8349
8350/* continuation for OP_IPUT_SHORT */
8351
8352    /*
8353     * Currently:
8354     *  r0 holds resolved field
8355     *  r9 holds object
8356     */
8357.LOP_IPUT_SHORT_finish:
8358    @bl      common_squeak4
8359    mov     r1, rINST, lsr #8           @ r1<- A+
8360    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8361    and     r1, r1, #15                 @ r1<- A
8362    cmp     r9, #0                      @ check object for null
8363    GET_VREG(r0, r1)                    @ r0<- fp[A]
8364    beq     common_errNullObject        @ object was null
8365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8366    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8367    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8368    GOTO_OPCODE(ip)                     @ jump to next instruction
8369
8370
8371/* continuation for OP_SGET */
8372
8373    /*
8374     * Continuation if the field has not yet been resolved.
8375     *  r1: BBBB field ref
8376     */
8377.LOP_SGET_resolve:
8378    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8379    EXPORT_PC()                         @ resolve() could throw, so export now
8380    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8381    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8382    cmp     r0, #0                      @ success?
8383    bne     .LOP_SGET_finish          @ yes, finish
8384    b       common_exceptionThrown      @ no, handle exception
8385
8386
8387/* continuation for OP_SGET_WIDE */
8388
8389    /*
8390     * Continuation if the field has not yet been resolved.
8391     *  r1: BBBB field ref
8392     */
8393.LOP_SGET_WIDE_resolve:
8394    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8395    EXPORT_PC()                         @ resolve() could throw, so export now
8396    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8397    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8398    cmp     r0, #0                      @ success?
8399    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8400    b       common_exceptionThrown      @ no, handle exception
8401
8402
8403/* continuation for OP_SGET_OBJECT */
8404
8405    /*
8406     * Continuation if the field has not yet been resolved.
8407     *  r1: BBBB field ref
8408     */
8409.LOP_SGET_OBJECT_resolve:
8410    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8411    EXPORT_PC()                         @ resolve() could throw, so export now
8412    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8413    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8414    cmp     r0, #0                      @ success?
8415    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8416    b       common_exceptionThrown      @ no, handle exception
8417
8418
8419/* continuation for OP_SGET_BOOLEAN */
8420
8421    /*
8422     * Continuation if the field has not yet been resolved.
8423     *  r1: BBBB field ref
8424     */
8425.LOP_SGET_BOOLEAN_resolve:
8426    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8427    EXPORT_PC()                         @ resolve() could throw, so export now
8428    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8429    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8430    cmp     r0, #0                      @ success?
8431    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8432    b       common_exceptionThrown      @ no, handle exception
8433
8434
8435/* continuation for OP_SGET_BYTE */
8436
8437    /*
8438     * Continuation if the field has not yet been resolved.
8439     *  r1: BBBB field ref
8440     */
8441.LOP_SGET_BYTE_resolve:
8442    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8443    EXPORT_PC()                         @ resolve() could throw, so export now
8444    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8445    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8446    cmp     r0, #0                      @ success?
8447    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8448    b       common_exceptionThrown      @ no, handle exception
8449
8450
8451/* continuation for OP_SGET_CHAR */
8452
8453    /*
8454     * Continuation if the field has not yet been resolved.
8455     *  r1: BBBB field ref
8456     */
8457.LOP_SGET_CHAR_resolve:
8458    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8459    EXPORT_PC()                         @ resolve() could throw, so export now
8460    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8461    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8462    cmp     r0, #0                      @ success?
8463    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8464    b       common_exceptionThrown      @ no, handle exception
8465
8466
8467/* continuation for OP_SGET_SHORT */
8468
8469    /*
8470     * Continuation if the field has not yet been resolved.
8471     *  r1: BBBB field ref
8472     */
8473.LOP_SGET_SHORT_resolve:
8474    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8475    EXPORT_PC()                         @ resolve() could throw, so export now
8476    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8477    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8478    cmp     r0, #0                      @ success?
8479    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8480    b       common_exceptionThrown      @ no, handle exception
8481
8482
8483/* continuation for OP_SPUT */
8484
8485    /*
8486     * Continuation if the field has not yet been resolved.
8487     *  r1: BBBB field ref
8488     */
8489.LOP_SPUT_resolve:
8490    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8491    EXPORT_PC()                         @ resolve() could throw, so export now
8492    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8493    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8494    cmp     r0, #0                      @ success?
8495    bne     .LOP_SPUT_finish          @ yes, finish
8496    b       common_exceptionThrown      @ no, handle exception
8497
8498
8499/* continuation for OP_SPUT_WIDE */
8500
8501    /*
8502     * Continuation if the field has not yet been resolved.
8503     *  r1: BBBB field ref
8504     *  r9: &fp[AA]
8505     */
8506.LOP_SPUT_WIDE_resolve:
8507    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8508    EXPORT_PC()                         @ resolve() could throw, so export now
8509    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8510    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8511    cmp     r0, #0                      @ success?
8512    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8513    b       common_exceptionThrown      @ no, handle exception
8514
8515
8516/* continuation for OP_SPUT_OBJECT */
8517
8518    /*
8519     * Continuation if the field has not yet been resolved.
8520     *  r1: BBBB field ref
8521     */
8522.LOP_SPUT_OBJECT_resolve:
8523    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8524    EXPORT_PC()                         @ resolve() could throw, so export now
8525    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8526    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8527    cmp     r0, #0                      @ success?
8528    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8529    b       common_exceptionThrown      @ no, handle exception
8530
8531
8532/* continuation for OP_SPUT_BOOLEAN */
8533
8534    /*
8535     * Continuation if the field has not yet been resolved.
8536     *  r1: BBBB field ref
8537     */
8538.LOP_SPUT_BOOLEAN_resolve:
8539    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8540    EXPORT_PC()                         @ resolve() could throw, so export now
8541    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8542    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8543    cmp     r0, #0                      @ success?
8544    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8545    b       common_exceptionThrown      @ no, handle exception
8546
8547
8548/* continuation for OP_SPUT_BYTE */
8549
8550    /*
8551     * Continuation if the field has not yet been resolved.
8552     *  r1: BBBB field ref
8553     */
8554.LOP_SPUT_BYTE_resolve:
8555    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8556    EXPORT_PC()                         @ resolve() could throw, so export now
8557    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8558    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8559    cmp     r0, #0                      @ success?
8560    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8561    b       common_exceptionThrown      @ no, handle exception
8562
8563
8564/* continuation for OP_SPUT_CHAR */
8565
8566    /*
8567     * Continuation if the field has not yet been resolved.
8568     *  r1: BBBB field ref
8569     */
8570.LOP_SPUT_CHAR_resolve:
8571    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8572    EXPORT_PC()                         @ resolve() could throw, so export now
8573    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8574    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8575    cmp     r0, #0                      @ success?
8576    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8577    b       common_exceptionThrown      @ no, handle exception
8578
8579
8580/* continuation for OP_SPUT_SHORT */
8581
8582    /*
8583     * Continuation if the field has not yet been resolved.
8584     *  r1: BBBB field ref
8585     */
8586.LOP_SPUT_SHORT_resolve:
8587    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8588    EXPORT_PC()                         @ resolve() could throw, so export now
8589    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8590    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8591    cmp     r0, #0                      @ success?
8592    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8593    b       common_exceptionThrown      @ no, handle exception
8594
8595
8596/* continuation for OP_INVOKE_VIRTUAL */
8597
8598    /*
8599     * At this point:
8600     *  r0 = resolved base method
8601     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8602     */
8603.LOP_INVOKE_VIRTUAL_continue:
8604    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8605    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8606    cmp     r1, #0                      @ is "this" null?
8607    beq     common_errNullObject        @ null "this", throw exception
8608    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8609    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8610    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8611    bl      common_invokeMethodNoRange @ continue on
8612
8613
8614/* continuation for OP_INVOKE_SUPER */
8615
8616    /*
8617     * At this point:
8618     *  r0 = resolved base method
8619     *  r9 = method->clazz
8620     */
8621.LOP_INVOKE_SUPER_continue:
8622    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8623    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8624    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8625    EXPORT_PC()                         @ must export for invoke
8626    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8627    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8628    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8629    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8630    bl      common_invokeMethodNoRange @ continue on
8631
8632.LOP_INVOKE_SUPER_resolve:
8633    mov     r0, r9                      @ r0<- method->clazz
8634    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8635    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8636    cmp     r0, #0                      @ got null?
8637    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8638    b       common_exceptionThrown      @ yes, handle exception
8639
8640    /*
8641     * Throw a NoSuchMethodError with the method name as the message.
8642     *  r0 = resolved base method
8643     */
8644.LOP_INVOKE_SUPER_nsm:
8645    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8646    b       common_errNoSuchMethod
8647
8648
8649/* continuation for OP_INVOKE_DIRECT */
8650
8651    /*
8652     * On entry:
8653     *  r1 = reference (BBBB or CCCC)
8654     *  r10 = "this" register
8655     */
8656.LOP_INVOKE_DIRECT_resolve:
8657    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8658    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8659    mov     r2, #METHOD_DIRECT          @ resolver method type
8660    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8661    cmp     r0, #0                      @ got null?
8662    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8663    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8664    b       common_exceptionThrown      @ yes, handle exception
8665
8666
8667/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8668
8669    /*
8670     * At this point:
8671     *  r0 = resolved base method
8672     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8673     */
8674.LOP_INVOKE_VIRTUAL_RANGE_continue:
8675    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8676    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8677    cmp     r1, #0                      @ is "this" null?
8678    beq     common_errNullObject        @ null "this", throw exception
8679    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8680    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8681    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8682    bl      common_invokeMethodRange @ continue on
8683
8684
8685/* continuation for OP_INVOKE_SUPER_RANGE */
8686
8687    /*
8688     * At this point:
8689     *  r0 = resolved base method
8690     *  r9 = method->clazz
8691     */
8692.LOP_INVOKE_SUPER_RANGE_continue:
8693    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8694    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8695    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8696    EXPORT_PC()                         @ must export for invoke
8697    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8698    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8699    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8700    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8701    bl      common_invokeMethodRange @ continue on
8702
8703.LOP_INVOKE_SUPER_RANGE_resolve:
8704    mov     r0, r9                      @ r0<- method->clazz
8705    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8706    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8707    cmp     r0, #0                      @ got null?
8708    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8709    b       common_exceptionThrown      @ yes, handle exception
8710
8711    /*
8712     * Throw a NoSuchMethodError with the method name as the message.
8713     *  r0 = resolved base method
8714     */
8715.LOP_INVOKE_SUPER_RANGE_nsm:
8716    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8717    b       common_errNoSuchMethod
8718
8719
8720/* continuation for OP_INVOKE_DIRECT_RANGE */
8721
8722    /*
8723     * On entry:
8724     *  r1 = reference (BBBB or CCCC)
8725     *  r10 = "this" register
8726     */
8727.LOP_INVOKE_DIRECT_RANGE_resolve:
8728    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8729    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8730    mov     r2, #METHOD_DIRECT          @ resolver method type
8731    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8732    cmp     r0, #0                      @ got null?
8733    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8734    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8735    b       common_exceptionThrown      @ yes, handle exception
8736
8737
8738/* continuation for OP_FLOAT_TO_LONG */
8739/*
8740 * Convert the float in r0 to a long in r0/r1.
8741 *
8742 * We have to clip values to long min/max per the specification.  The
8743 * expected common case is a "reasonable" value that converts directly
8744 * to modest integer.  The EABI convert function isn't doing this for us.
8745 */
8746f2l_doconv:
8747    stmfd   sp!, {r4, lr}
8748    mov     r1, #0x5f000000             @ (float)maxlong
8749    mov     r4, r0
8750    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8751    cmp     r0, #0                      @ nonzero == yes
8752    mvnne   r0, #0                      @ return maxlong (7fffffff)
8753    mvnne   r1, #0x80000000
8754    ldmnefd sp!, {r4, pc}
8755
8756    mov     r0, r4                      @ recover arg
8757    mov     r1, #0xdf000000             @ (float)minlong
8758    bl      __aeabi_fcmple              @ is arg <= minlong?
8759    cmp     r0, #0                      @ nonzero == yes
8760    movne   r0, #0                      @ return minlong (80000000)
8761    movne   r1, #0x80000000
8762    ldmnefd sp!, {r4, pc}
8763
8764    mov     r0, r4                      @ recover arg
8765    mov     r1, r4
8766    bl      __aeabi_fcmpeq              @ is arg == self?
8767    cmp     r0, #0                      @ zero == no
8768    moveq   r1, #0                      @ return zero for NaN
8769    ldmeqfd sp!, {r4, pc}
8770
8771    mov     r0, r4                      @ recover arg
8772    bl      __aeabi_f2lz                @ convert float to long
8773    ldmfd   sp!, {r4, pc}
8774
8775
8776/* continuation for OP_DOUBLE_TO_LONG */
8777/*
8778 * Convert the double in r0/r1 to a long in r0/r1.
8779 *
8780 * We have to clip values to long min/max per the specification.  The
8781 * expected common case is a "reasonable" value that converts directly
8782 * to modest integer.  The EABI convert function isn't doing this for us.
8783 */
8784d2l_doconv:
8785    stmfd   sp!, {r4, r5, lr}           @ save regs
8786    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8787    add     r3, #0x00e00000             @  0x43e00000
8788    mov     r2, #0                      @ maxlong, as a double (low word)
8789    sub     sp, sp, #4                  @ align for EABI
8790    mov     r4, r0                      @ save a copy of r0
8791    mov     r5, r1                      @  and r1
8792    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8793    cmp     r0, #0                      @ nonzero == yes
8794    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8795    mvnne   r1, #0x80000000
8796    bne     1f
8797
8798    mov     r0, r4                      @ recover arg
8799    mov     r1, r5
8800    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8801    add     r3, #0x00e00000             @  0xc3e00000
8802    mov     r2, #0                      @ minlong, as a double (low word)
8803    bl      __aeabi_dcmple              @ is arg <= minlong?
8804    cmp     r0, #0                      @ nonzero == yes
8805    movne   r0, #0                      @ return minlong (8000000000000000)
8806    movne   r1, #0x80000000
8807    bne     1f
8808
8809    mov     r0, r4                      @ recover arg
8810    mov     r1, r5
8811    mov     r2, r4                      @ compare against self
8812    mov     r3, r5
8813    bl      __aeabi_dcmpeq              @ is arg == self?
8814    cmp     r0, #0                      @ zero == no
8815    moveq   r1, #0                      @ return zero for NaN
8816    beq     1f
8817
8818    mov     r0, r4                      @ recover arg
8819    mov     r1, r5
8820    bl      __aeabi_d2lz                @ convert double to long
8821
88221:
8823    add     sp, sp, #4
8824    ldmfd   sp!, {r4, r5, pc}
8825
8826
8827/* continuation for OP_MUL_LONG */
8828
8829.LOP_MUL_LONG_finish:
8830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8831    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8832    GOTO_OPCODE(ip)                     @ jump to next instruction
8833
8834
8835/* continuation for OP_SHL_LONG */
8836
8837.LOP_SHL_LONG_finish:
8838    mov     r0, r0, asl r2              @  r0<- r0 << r2
8839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8840    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8841    GOTO_OPCODE(ip)                     @ jump to next instruction
8842
8843
8844/* continuation for OP_SHR_LONG */
8845
8846.LOP_SHR_LONG_finish:
8847    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8849    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8850    GOTO_OPCODE(ip)                     @ jump to next instruction
8851
8852
8853/* continuation for OP_USHR_LONG */
8854
8855.LOP_USHR_LONG_finish:
8856    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8857    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8858    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8859    GOTO_OPCODE(ip)                     @ jump to next instruction
8860
8861
8862/* continuation for OP_SHL_LONG_2ADDR */
8863
8864.LOP_SHL_LONG_2ADDR_finish:
8865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8866    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8867    GOTO_OPCODE(ip)                     @ jump to next instruction
8868
8869
8870/* continuation for OP_SHR_LONG_2ADDR */
8871
8872.LOP_SHR_LONG_2ADDR_finish:
8873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8874    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8875    GOTO_OPCODE(ip)                     @ jump to next instruction
8876
8877
8878/* continuation for OP_USHR_LONG_2ADDR */
8879
8880.LOP_USHR_LONG_2ADDR_finish:
8881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8882    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8883    GOTO_OPCODE(ip)                     @ jump to next instruction
8884
8885
8886/* continuation for OP_EXECUTE_INLINE */
8887
8888    /*
8889     * Extract args, call function.
8890     *  r0 = #of args (0-4)
8891     *  r10 = call index
8892     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8893     *
8894     * Other ideas:
8895     * - Use a jump table from the main piece to jump directly into the
8896     *   AND/LDR pairs.  Costs a data load, saves a branch.
8897     * - Have five separate pieces that do the loading, so we can work the
8898     *   interleave a little better.  Increases code size.
8899     */
8900.LOP_EXECUTE_INLINE_continue:
8901    rsb     r0, r0, #4                  @ r0<- 4-r0
8902    FETCH(r9, 2)                        @ r9<- FEDC
8903    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8904    bl      common_abort                @ (skipped due to ARM prefetch)
89054:  and     ip, r9, #0xf000             @ isolate F
8906    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89073:  and     ip, r9, #0x0f00             @ isolate E
8908    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89092:  and     ip, r9, #0x00f0             @ isolate D
8910    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
89111:  and     ip, r9, #0x000f             @ isolate C
8912    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
89130:
8914    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8915    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8916    @ (not reached)
8917
8918.LOP_EXECUTE_INLINE_table:
8919    .word   gDvmInlineOpsTable
8920
8921
8922    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8923    .global dvmAsmSisterEnd
8924dvmAsmSisterEnd:
8925
8926/* File: armv5te/footer.S */
8927
8928/*
8929 * ===========================================================================
8930 *  Common subroutines and data
8931 * ===========================================================================
8932 */
8933
8934
8935
8936    .text
8937    .align  2
8938
8939#if defined(WITH_JIT)
8940#if defined(WITH_SELF_VERIFICATION)
8941    .global dvmJitToInterpPunt
8942dvmJitToInterpPunt:
8943    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
8944    b      dvmJitSelfVerificationEnd    @ doesn't return
8945
8946    .global dvmJitToInterpSingleStep
8947dvmJitToInterpSingleStep:
8948    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
8949    b      dvmJitSelfVerificationEnd    @ doesn't return
8950
8951    .global dvmJitToTraceSelect
8952dvmJitToTraceSelect:
8953    ldr    r0,[r14, #-1]                @ pass our target PC
8954    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
8955    b      dvmJitSelfVerificationEnd    @ doesn't return
8956
8957    .global dvmJitToBackwardBranch
8958dvmJitToBackwardBranch:
8959    ldr    r0,[r14, #-1]                @ pass our target PC
8960    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
8961    b      dvmJitSelfVerificationEnd    @ doesn't return
8962
8963    .global dvmJitToInterpNormal
8964dvmJitToInterpNormal:
8965    ldr    r0,[r14, #-1]                @ pass our target PC
8966    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
8967    b      dvmJitSelfVerificationEnd    @ doesn't return
8968
8969    .global dvmJitToInterpNoChain
8970dvmJitToInterpNoChain:
8971    mov    r0,rPC                       @ pass our target PC
8972    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
8973    b      dvmJitSelfVerificationEnd    @ doesn't return
8974#else
8975/*
8976 * Return from the translation cache to the interpreter when the compiler is
8977 * having issues translating/executing a Dalvik instruction. We have to skip
8978 * the code cache lookup otherwise it is possible to indefinitely bouce
8979 * between the interpreter and the code cache if the instruction that fails
8980 * to be compiled happens to be at a trace start.
8981 */
8982    .global dvmJitToInterpPunt
8983dvmJitToInterpPunt:
8984    mov    rPC, r0
8985#ifdef EXIT_STATS
8986    mov    r0,lr
8987    bl     dvmBumpPunt;
8988#endif
8989    EXPORT_PC()
8990    adrl   rIBASE, dvmAsmInstructionStart
8991    FETCH_INST()
8992    GET_INST_OPCODE(ip)
8993    GOTO_OPCODE(ip)
8994
8995/*
8996 * Return to the interpreter to handle a single instruction.
8997 * On entry:
8998 *    r0 <= PC
8999 *    r1 <= PC of resume instruction
9000 *    lr <= resume point in translation
9001 */
9002    .global dvmJitToInterpSingleStep
9003dvmJitToInterpSingleStep:
9004    str    lr,[rGLUE,#offGlue_jitResume]
9005    str    r1,[rGLUE,#offGlue_jitResumePC]
9006    mov    r1,#kInterpEntryInstr
9007    @ enum is 4 byte in aapcs-EABI
9008    str    r1, [rGLUE, #offGlue_entryPoint]
9009    mov    rPC,r0
9010    EXPORT_PC()
9011    adrl   rIBASE, dvmAsmInstructionStart
9012    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9013    str    r2,[rGLUE,#offGlue_jitState]
9014    mov    r1,#1                  @ set changeInterp to bail to debug interp
9015    b      common_gotoBail
9016
9017
9018/*
9019 * Return from the translation cache and immediately request
9020 * a translation for the exit target.  Commonly used following
9021 * invokes.
9022 */
9023    .global dvmJitToTraceSelect
9024dvmJitToTraceSelect:
9025    ldr    rPC,[r14, #-1]           @ get our target PC
9026    add    rINST,r14,#-5            @ save start of chain branch
9027    mov    r0,rPC
9028    bl     dvmJitGetCodeAddr        @ Is there a translation?
9029    cmp    r0,#0
9030    beq    2f
9031    mov    r1,rINST
9032    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9033    cmp    r0,#0                    @ successful chain?
9034    bxne   r0                       @ continue native execution
9035    b      toInterpreter            @ didn't chain - resume with interpreter
9036
9037/* No translation, so request one if profiling isn't disabled*/
90382:
9039    adrl   rIBASE, dvmAsmInstructionStart
9040    GET_JIT_PROF_TABLE(r0)
9041    FETCH_INST()
9042    cmp    r0, #0
9043    bne    common_selectTrace
9044    GET_INST_OPCODE(ip)
9045    GOTO_OPCODE(ip)
9046
9047/*
9048 * Return from the translation cache to the interpreter.
9049 * The return was done with a BLX from thumb mode, and
9050 * the following 32-bit word contains the target rPC value.
9051 * Note that lr (r14) will have its low-order bit set to denote
9052 * its thumb-mode origin.
9053 *
9054 * We'll need to stash our lr origin away, recover the new
9055 * target and then check to see if there is a translation available
9056 * for our new target.  If so, we do a translation chain and
9057 * go back to native execution.  Otherwise, it's back to the
9058 * interpreter (after treating this entry as a potential
9059 * trace start).
9060 */
9061    .global dvmJitToInterpNormal
9062dvmJitToInterpNormal:
9063    ldr    rPC,[r14, #-1]           @ get our target PC
9064    add    rINST,r14,#-5            @ save start of chain branch
9065#ifdef EXIT_STATS
9066    bl     dvmBumpNormal
9067#endif
9068    mov    r0,rPC
9069    bl     dvmJitGetCodeAddr        @ Is there a translation?
9070    cmp    r0,#0
9071    beq    toInterpreter            @ go if not, otherwise do chain
9072    mov    r1,rINST
9073    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9074    cmp    r0,#0                    @ successful chain?
9075    bxne   r0                       @ continue native execution
9076    b      toInterpreter            @ didn't chain - resume with interpreter
9077
9078/*
9079 * Return from the translation cache to the interpreter to do method invocation.
9080 * Check if translation exists for the callee, but don't chain to it.
9081 */
9082    .global dvmJitToInterpNoChain
9083dvmJitToInterpNoChain:
9084#ifdef EXIT_STATS
9085    bl     dvmBumpNoChain
9086#endif
9087    mov    r0,rPC
9088    bl     dvmJitGetCodeAddr        @ Is there a translation?
9089    cmp    r0,#0
9090    bxne   r0                       @ continue native execution if so
9091#endif
9092
9093/*
9094 * No translation, restore interpreter regs and start interpreting.
9095 * rGLUE & rFP were preserved in the translated code, and rPC has
9096 * already been restored by the time we get here.  We'll need to set
9097 * up rIBASE & rINST, and load the address of the JitTable into r0.
9098 */
9099toInterpreter:
9100    EXPORT_PC()
9101    adrl   rIBASE, dvmAsmInstructionStart
9102    FETCH_INST()
9103    GET_JIT_PROF_TABLE(r0)
9104    @ NOTE: intended fallthrough
9105/*
9106 * Common code to update potential trace start counter, and initiate
9107 * a trace-build if appropriate.  On entry, rPC should point to the
9108 * next instruction to execute, and rINST should be already loaded with
9109 * the next opcode word, and r0 holds a pointer to the jit profile
9110 * table (pJitProfTable).
9111 */
9112common_testUpdateProfile:
9113    cmp     r0,#0
9114    GET_INST_OPCODE(ip)
9115    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9116
9117common_updateProfile:
9118    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9119    lsl     r3,r3,#23          @ shift out excess 511
9120    ldrb    r1,[r0,r3,lsr #23] @ get counter
9121    GET_INST_OPCODE(ip)
9122    subs    r1,r1,#1           @ decrement counter
9123    strb    r1,[r0,r3,lsr #23] @ and store it
9124    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9125
9126/*
9127 * Here, we switch to the debug interpreter to request
9128 * trace selection.  First, though, check to see if there
9129 * is already a native translation in place (and, if so,
9130 * jump to it now).
9131 */
9132    mov     r1,#255
9133    strb    r1,[r0,r3,lsr #23] @ reset counter
9134    EXPORT_PC()
9135    mov     r0,rPC
9136    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9137    cmp     r0,#0
9138    beq     common_selectTrace
9139#if !defined(WITH_SELF_VERIFICATION)
9140    bxne    r0                          @ jump to the translation
9141#else
9142    bne     dvmJitSelfVerificationStart @ set up self verification
9143#endif
9144common_selectTrace:
9145    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9146    str     r2,[rGLUE,#offGlue_jitState]
9147    mov     r2,#kInterpEntryInstr       @ normal entry reason
9148    str     r2,[rGLUE,#offGlue_entryPoint]
9149    mov     r1,#1                       @ set changeInterp
9150    b       common_gotoBail
9151
9152#if defined(WITH_SELF_VERIFICATION)
9153/*
9154 * Save PC and registers to shadow memory for self verification mode
9155 * before jumping to native translation.
9156 */
9157dvmJitSelfVerificationStart:
9158    sub     sp,sp,#4                    @ allocate stack space
9159    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
9160    mov     r0,rPC                      @ r0<- program counter
9161    mov     r1,rFP                      @ r1<- frame pointer
9162    mov     r2,rGLUE                    @ r2<- InterpState pointer
9163    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9164    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
9165    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
9166    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
9167    add     sp,sp,#4                    @ restore stack
9168    bx      r0                          @ jump to the translation
9169
9170/*
9171 * Restore PC, registers, and interpState to original values
9172 * before jumping back to the interpreter.
9173 */
9174dvmJitSelfVerificationEnd:
9175    mov    r1,rFP                        @ pass ending fp
9176    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9177    ldr    rPC,[r0,#0]                   @ restore PC
9178    ldr    rFP,[r0,#4]                   @ restore FP
9179    ldr    rGLUE,[r0,#8]                 @ restore InterpState
9180    ldr    r1,[r0,#12]                   @ get exitPoint
9181    cmp    r1,#0                         @ check for punt condition
9182    beq    1f
9183    mov    r2,#kJitSelfVerification      @ ask for self verification
9184    str    r2,[rGLUE,#offGlue_jitState]
9185    mov    r2,#kInterpEntryInstr         @ normal entry reason
9186    str    r2,[rGLUE,#offGlue_entryPoint]
9187    mov    r1,#1                         @ set changeInterp
9188    b      common_gotoBail
9189
91901:                                       @ exit to interpreter without check
9191    EXPORT_PC()
9192    adrl   rIBASE, dvmAsmInstructionStart
9193    FETCH_INST()
9194    GET_INST_OPCODE(ip)
9195    GOTO_OPCODE(ip)
9196#endif
9197
9198#endif
9199
9200/*
9201 * Common code when a backward branch is taken.
9202 *
9203 * On entry:
9204 *  r9 is PC adjustment *in bytes*
9205 */
9206common_backwardBranch:
9207    mov     r0, #kInterpEntryInstr
9208    bl      common_periodicChecks
9209#if defined(WITH_JIT)
9210    GET_JIT_PROF_TABLE(r0)
9211    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9212    cmp     r0,#0
9213    bne     common_updateProfile
9214    GET_INST_OPCODE(ip)
9215    GOTO_OPCODE(ip)
9216#else
9217    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9219    GOTO_OPCODE(ip)                     @ jump to next instruction
9220#endif
9221
9222
9223/*
9224 * Need to see if the thread needs to be suspended or debugger/profiler
9225 * activity has begun.
9226 *
9227 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9228 * have to do the second ldr.
9229 *
9230 * TODO: reduce this so we're just checking a single location.
9231 *
9232 * On entry:
9233 *  r0 is reentry type, e.g. kInterpEntryInstr
9234 *  r9 is trampoline PC adjustment *in bytes*
9235 */
9236common_periodicChecks:
9237    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9238
9239    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9240    str     r0, [rGLUE, #offGlue_entryPoint]
9241
9242#if defined(WITH_DEBUGGER)
9243    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9244#endif
9245#if defined(WITH_PROFILER)
9246    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9247#endif
9248
9249    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9250
9251#if defined(WITH_DEBUGGER)
9252    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9253#endif
9254#if defined (WITH_PROFILER)
9255    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9256#endif
9257
9258    cmp     r3, #0                      @ suspend pending?
9259    bne     2f                          @ yes, do full suspension check
9260
9261#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9262# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9263    orrs    r1, r1, r2                  @ r1<- r1 | r2
9264    cmp     r1, #0                      @ debugger attached or profiler started?
9265# elif defined(WITH_DEBUGGER)
9266    cmp     r1, #0                      @ debugger attached?
9267# elif defined(WITH_PROFILER)
9268    cmp     r2, #0                      @ profiler started?
9269# endif
9270    bne     3f                          @ debugger/profiler, switch interp
9271#endif
9272
9273    bx      lr                          @ nothing to do, return
9274
92752:  @ check suspend
9276    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9277    EXPORT_PC()                         @ need for precise GC
9278    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9279
92803:  @ debugger/profiler enabled, bail out
9281    add     rPC, rPC, r9                @ update rPC
9282    mov     r1, #1                      @ "want switch" = true
9283    b       common_gotoBail
9284
9285
9286/*
9287 * The equivalent of "goto bail", this calls through the "bail handler".
9288 *
9289 * State registers will be saved to the "glue" area before bailing.
9290 *
9291 * On entry:
9292 *  r1 is "bool changeInterp", indicating if we want to switch to the
9293 *     other interpreter or just bail all the way out
9294 */
9295common_gotoBail:
9296    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9297    mov     r0, rGLUE                   @ r0<- glue ptr
9298    b       dvmMterpStdBail             @ call(glue, changeInterp)
9299
9300    @add     r1, r1, #1                  @ using (boolean+1)
9301    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9302    @bl      _longjmp                    @ does not return
9303    @bl      common_abort
9304
9305
9306/*
9307 * Common code for method invocation with range.
9308 *
9309 * On entry:
9310 *  r0 is "Method* methodToCall", the method we're trying to call
9311 */
9312common_invokeMethodRange:
9313.LinvokeNewRange:
9314    @ prepare to copy args to "outs" area of current frame
9315    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9316    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9317    beq     .LinvokeArgsDone            @ if no args, skip the rest
9318    FETCH(r1, 2)                        @ r1<- CCCC
9319
9320    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9321    @ (very few methods have > 10 args; could unroll for common cases)
9322    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9323    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9324    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
93251:  ldr     r1, [r3], #4                @ val = *fp++
9326    subs    r2, r2, #1                  @ count--
9327    str     r1, [r10], #4               @ *outs++ = val
9328    bne     1b                          @ ...while count != 0
9329    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9330    b       .LinvokeArgsDone
9331
9332/*
9333 * Common code for method invocation without range.
9334 *
9335 * On entry:
9336 *  r0 is "Method* methodToCall", the method we're trying to call
9337 */
9338common_invokeMethodNoRange:
9339.LinvokeNewNoRange:
9340    @ prepare to copy args to "outs" area of current frame
9341    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9342    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9343    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9344    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9345    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9346    beq     .LinvokeArgsDone
9347
9348    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9349.LinvokeNonRange:
9350    rsb     r2, r2, #5                  @ r2<- 5-r2
9351    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9352    bl      common_abort                @ (skipped due to ARM prefetch)
93535:  and     ip, rINST, #0x0f00          @ isolate A
9354    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9355    mov     r0, r0                      @ nop
9356    str     r2, [r10, #-4]!             @ *--outs = vA
93574:  and     ip, r1, #0xf000             @ isolate G
9358    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9359    mov     r0, r0                      @ nop
9360    str     r2, [r10, #-4]!             @ *--outs = vG
93613:  and     ip, r1, #0x0f00             @ isolate F
9362    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9363    mov     r0, r0                      @ nop
9364    str     r2, [r10, #-4]!             @ *--outs = vF
93652:  and     ip, r1, #0x00f0             @ isolate E
9366    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9367    mov     r0, r0                      @ nop
9368    str     r2, [r10, #-4]!             @ *--outs = vE
93691:  and     ip, r1, #0x000f             @ isolate D
9370    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9371    mov     r0, r0                      @ nop
9372    str     r2, [r10, #-4]!             @ *--outs = vD
93730:  @ fall through to .LinvokeArgsDone
9374
9375.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9376    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9377    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9378    @ find space for the new stack frame, check for overflow
9379    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9380    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9381    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9382@    bl      common_dumpRegs
9383    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9384    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9385    cmp     r3, r9                      @ bottom < interpStackEnd?
9386    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9387    blt     .LstackOverflow             @ yes, this frame will overflow stack
9388
9389    @ set up newSaveArea
9390#ifdef EASY_GDB
9391    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9392    str     ip, [r10, #offStackSaveArea_prevSave]
9393#endif
9394    str     rFP, [r10, #offStackSaveArea_prevFrame]
9395    str     rPC, [r10, #offStackSaveArea_savedPc]
9396#if defined(WITH_JIT)
9397    mov     r9, #0
9398    str     r9, [r10, #offStackSaveArea_returnAddr]
9399#endif
9400    str     r0, [r10, #offStackSaveArea_method]
9401    tst     r3, #ACC_NATIVE
9402    bne     .LinvokeNative
9403
9404    /*
9405    stmfd   sp!, {r0-r3}
9406    bl      common_printNewline
9407    mov     r0, rFP
9408    mov     r1, #0
9409    bl      dvmDumpFp
9410    ldmfd   sp!, {r0-r3}
9411    stmfd   sp!, {r0-r3}
9412    mov     r0, r1
9413    mov     r1, r10
9414    bl      dvmDumpFp
9415    bl      common_printNewline
9416    ldmfd   sp!, {r0-r3}
9417    */
9418
9419    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9420    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9421    mov     rPC, r2                         @ publish new rPC
9422    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9423
9424    @ Update "glue" values for the new method
9425    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9426    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9427    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9428#if defined(WITH_JIT)
9429    GET_JIT_PROF_TABLE(r0)
9430    mov     rFP, r1                         @ fp = newFp
9431    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9432    mov     rINST, r9                       @ publish new rINST
9433    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9434    cmp     r0,#0
9435    bne     common_updateProfile
9436    GOTO_OPCODE(ip)                         @ jump to next instruction
9437#else
9438    mov     rFP, r1                         @ fp = newFp
9439    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9440    mov     rINST, r9                       @ publish new rINST
9441    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9442    GOTO_OPCODE(ip)                         @ jump to next instruction
9443#endif
9444
9445.LinvokeNative:
9446    @ Prep for the native call
9447    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9448    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9449    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9450    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9451    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9452    mov     r9, r3                      @ r9<- glue->self (preserve)
9453
9454    mov     r2, r0                      @ r2<- methodToCall
9455    mov     r0, r1                      @ r0<- newFp (points to args)
9456    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9457
9458#ifdef ASSIST_DEBUGGER
9459    /* insert fake function header to help gdb find the stack frame */
9460    b       .Lskip
9461    .type   dalvik_mterp, %function
9462dalvik_mterp:
9463    .fnstart
9464    MTERP_ENTRY1
9465    MTERP_ENTRY2
9466.Lskip:
9467#endif
9468
9469    @mov     lr, pc                      @ set return addr
9470    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9471    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9472
9473    @ native return; r9=self, r10=newSaveArea
9474    @ equivalent to dvmPopJniLocals
9475    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9476    ldr     r1, [r9, #offThread_exception] @ check for exception
9477    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9478    cmp     r1, #0                      @ null?
9479    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9480    bne     common_exceptionThrown      @ no, handle exception
9481
9482    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9483    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9484    GOTO_OPCODE(ip)                     @ jump to next instruction
9485
9486.LstackOverflow:    @ r0=methodToCall
9487    mov     r1, r0                      @ r1<- methodToCall
9488    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9489    bl      dvmHandleStackOverflow
9490    b       common_exceptionThrown
9491#ifdef ASSIST_DEBUGGER
9492    .fnend
9493#endif
9494
9495
9496    /*
9497     * Common code for method invocation, calling through "glue code".
9498     *
9499     * TODO: now that we have range and non-range invoke handlers, this
9500     *       needs to be split into two.  Maybe just create entry points
9501     *       that set r9 and jump here?
9502     *
9503     * On entry:
9504     *  r0 is "Method* methodToCall", the method we're trying to call
9505     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9506     */
9507     .if    0
9508.LinvokeOld:
9509    sub     sp, sp, #8                  @ space for args + pad
9510    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9511    mov     r2, r0                      @ A2<- methodToCall
9512    mov     r0, rGLUE                   @ A0<- glue
9513    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9514    mov     r1, r9                      @ A1<- methodCallRange
9515    mov     r3, rINST, lsr #8           @ A3<- AA
9516    str     ip, [sp, #0]                @ A4<- ip
9517    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9518    add     sp, sp, #8                  @ remove arg area
9519    b       common_resumeAfterGlueCall  @ continue to next instruction
9520    .endif
9521
9522
9523
9524/*
9525 * Common code for handling a return instruction.
9526 *
9527 * This does not return.
9528 */
9529common_returnFromMethod:
9530.LreturnNew:
9531    mov     r0, #kInterpEntryReturn
9532    mov     r9, #0
9533    bl      common_periodicChecks
9534
9535    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9536    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9537    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9538    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9539                                        @ r2<- method we're returning to
9540    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9541    cmp     r2, #0                      @ is this a break frame?
9542    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9543    mov     r1, #0                      @ "want switch" = false
9544    beq     common_gotoBail             @ break frame, bail out completely
9545
9546    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9547    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9548    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9549    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9550#if defined(WITH_JIT)
9551    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
9552    GET_JIT_PROF_TABLE(r0)
9553    mov     rPC, r9                     @ publish new rPC
9554    str     r1, [rGLUE, #offGlue_methodClassDex]
9555    cmp     r3, #0                      @ caller is compiled code
9556    blxne   r3
9557    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9558    cmp     r0,#0
9559    bne     common_updateProfile
9560    GOTO_OPCODE(ip)                     @ jump to next instruction
9561#else
9562    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9563    mov     rPC, r9                     @ publish new rPC
9564    str     r1, [rGLUE, #offGlue_methodClassDex]
9565    GOTO_OPCODE(ip)                     @ jump to next instruction
9566#endif
9567
9568    /*
9569     * Return handling, calls through "glue code".
9570     */
9571     .if    0
9572.LreturnOld:
9573    SAVE_PC_FP_TO_GLUE()                @ export state
9574    mov     r0, rGLUE                   @ arg to function
9575    bl      dvmMterp_returnFromMethod
9576    b       common_resumeAfterGlueCall
9577    .endif
9578
9579
9580/*
9581 * Somebody has thrown an exception.  Handle it.
9582 *
9583 * If the exception processing code returns to us (instead of falling
9584 * out of the interpreter), continue with whatever the next instruction
9585 * now happens to be.
9586 *
9587 * This does not return.
9588 */
9589     .global dvmMterpCommonExceptionThrown
9590dvmMterpCommonExceptionThrown:
9591common_exceptionThrown:
9592.LexceptionNew:
9593    mov     r0, #kInterpEntryThrow
9594    mov     r9, #0
9595    bl      common_periodicChecks
9596
9597#if defined(WITH_JIT)
9598    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9599    str     r2,[rGLUE,#offGlue_jitState]
9600#endif
9601
9602    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9603    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9604    mov     r1, r10                     @ r1<- self
9605    mov     r0, r9                      @ r0<- exception
9606    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9607    mov     r3, #0                      @ r3<- NULL
9608    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9609
9610    /* set up args and a local for "&fp" */
9611    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9612    str     rFP, [sp, #-4]!             @ *--sp = fp
9613    mov     ip, sp                      @ ip<- &fp
9614    mov     r3, #0                      @ r3<- false
9615    str     ip, [sp, #-4]!              @ *--sp = &fp
9616    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9617    mov     r0, r10                     @ r0<- self
9618    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9619    mov     r2, r9                      @ r2<- exception
9620    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9621    mov     r1, r1, asr #1              @ r1<- offset in code units
9622
9623    /* call, r0 gets catchRelPc (a code-unit offset) */
9624    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9625
9626    /* fix earlier stack overflow if necessary; may trash rFP */
9627    ldrb    r1, [r10, #offThread_stackOverflowed]
9628    cmp     r1, #0                      @ did we overflow earlier?
9629    beq     1f                          @ no, skip ahead
9630    mov     rFP, r0                     @ save relPc result in rFP
9631    mov     r0, r10                     @ r0<- self
9632    bl      dvmCleanupStackOverflow     @ call(self)
9633    mov     r0, rFP                     @ restore result
96341:
9635
9636    /* update frame pointer and check result from dvmFindCatchBlock */
9637    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9638    cmp     r0, #0                      @ is catchRelPc < 0?
9639    add     sp, sp, #8                  @ restore stack
9640    bmi     .LnotCaughtLocally
9641
9642    /* adjust locals to match self->curFrame and updated PC */
9643    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9644    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9645    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9646    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9647    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9648    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9649    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9650    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9651
9652    /* release the tracked alloc on the exception */
9653    mov     r0, r9                      @ r0<- exception
9654    mov     r1, r10                     @ r1<- self
9655    bl      dvmReleaseTrackedAlloc      @ release the exception
9656
9657    /* restore the exception if the handler wants it */
9658    FETCH_INST()                        @ load rINST from rPC
9659    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9660    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9661    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9662    GOTO_OPCODE(ip)                     @ jump to next instruction
9663
9664.LnotCaughtLocally: @ r9=exception, r10=self
9665    /* fix stack overflow if necessary */
9666    ldrb    r1, [r10, #offThread_stackOverflowed]
9667    cmp     r1, #0                      @ did we overflow earlier?
9668    movne   r0, r10                     @ if yes: r0<- self
9669    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9670
9671    @ may want to show "not caught locally" debug messages here
9672#if DVM_SHOW_EXCEPTION >= 2
9673    /* call __android_log_print(prio, tag, format, ...) */
9674    /* "Exception %s from %s:%d not caught locally" */
9675    @ dvmLineNumFromPC(method, pc - method->insns)
9676    ldr     r0, [rGLUE, #offGlue_method]
9677    ldr     r1, [r0, #offMethod_insns]
9678    sub     r1, rPC, r1
9679    asr     r1, r1, #1
9680    bl      dvmLineNumFromPC
9681    str     r0, [sp, #-4]!
9682    @ dvmGetMethodSourceFile(method)
9683    ldr     r0, [rGLUE, #offGlue_method]
9684    bl      dvmGetMethodSourceFile
9685    str     r0, [sp, #-4]!
9686    @ exception->clazz->descriptor
9687    ldr     r3, [r9, #offObject_clazz]
9688    ldr     r3, [r3, #offClassObject_descriptor]
9689    @
9690    ldr     r2, strExceptionNotCaughtLocally
9691    ldr     r1, strLogTag
9692    mov     r0, #3                      @ LOG_DEBUG
9693    bl      __android_log_print
9694#endif
9695    str     r9, [r10, #offThread_exception] @ restore exception
9696    mov     r0, r9                      @ r0<- exception
9697    mov     r1, r10                     @ r1<- self
9698    bl      dvmReleaseTrackedAlloc      @ release the exception
9699    mov     r1, #0                      @ "want switch" = false
9700    b       common_gotoBail             @ bail out
9701
9702
9703    /*
9704     * Exception handling, calls through "glue code".
9705     */
9706    .if     0
9707.LexceptionOld:
9708    SAVE_PC_FP_TO_GLUE()                @ export state
9709    mov     r0, rGLUE                   @ arg to function
9710    bl      dvmMterp_exceptionThrown
9711    b       common_resumeAfterGlueCall
9712    .endif
9713
9714
9715/*
9716 * After returning from a "glued" function, pull out the updated
9717 * values and start executing at the next instruction.
9718 */
9719common_resumeAfterGlueCall:
9720    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9721    FETCH_INST()                        @ load rINST from rPC
9722    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9723    GOTO_OPCODE(ip)                     @ jump to next instruction
9724
9725/*
9726 * Invalid array index.
9727 */
9728common_errArrayIndex:
9729    EXPORT_PC()
9730    ldr     r0, strArrayIndexException
9731    mov     r1, #0
9732    bl      dvmThrowException
9733    b       common_exceptionThrown
9734
9735/*
9736 * Invalid array value.
9737 */
9738common_errArrayStore:
9739    EXPORT_PC()
9740    ldr     r0, strArrayStoreException
9741    mov     r1, #0
9742    bl      dvmThrowException
9743    b       common_exceptionThrown
9744
9745/*
9746 * Integer divide or mod by zero.
9747 */
9748common_errDivideByZero:
9749    EXPORT_PC()
9750    ldr     r0, strArithmeticException
9751    ldr     r1, strDivideByZero
9752    bl      dvmThrowException
9753    b       common_exceptionThrown
9754
9755/*
9756 * Attempt to allocate an array with a negative size.
9757 */
9758common_errNegativeArraySize:
9759    EXPORT_PC()
9760    ldr     r0, strNegativeArraySizeException
9761    mov     r1, #0
9762    bl      dvmThrowException
9763    b       common_exceptionThrown
9764
9765/*
9766 * Invocation of a non-existent method.
9767 */
9768common_errNoSuchMethod:
9769    EXPORT_PC()
9770    ldr     r0, strNoSuchMethodError
9771    mov     r1, #0
9772    bl      dvmThrowException
9773    b       common_exceptionThrown
9774
9775/*
9776 * We encountered a null object when we weren't expecting one.  We
9777 * export the PC, throw a NullPointerException, and goto the exception
9778 * processing code.
9779 */
9780common_errNullObject:
9781    EXPORT_PC()
9782    ldr     r0, strNullPointerException
9783    mov     r1, #0
9784    bl      dvmThrowException
9785    b       common_exceptionThrown
9786
9787/*
9788 * For debugging, cause an immediate fault.  The source address will
9789 * be in lr (use a bl instruction to jump here).
9790 */
9791common_abort:
9792    ldr     pc, .LdeadFood
9793.LdeadFood:
9794    .word   0xdeadf00d
9795
9796/*
9797 * Spit out a "we were here", preserving all registers.  (The attempt
9798 * to save ip won't work, but we need to save an even number of
9799 * registers for EABI 64-bit stack alignment.)
9800 */
9801    .macro  SQUEAK num
9802common_squeak\num:
9803    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9804    ldr     r0, strSqueak
9805    mov     r1, #\num
9806    bl      printf
9807    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9808    bx      lr
9809    .endm
9810
9811    SQUEAK  0
9812    SQUEAK  1
9813    SQUEAK  2
9814    SQUEAK  3
9815    SQUEAK  4
9816    SQUEAK  5
9817
9818/*
9819 * Spit out the number in r0, preserving registers.
9820 */
9821common_printNum:
9822    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9823    mov     r1, r0
9824    ldr     r0, strSqueak
9825    bl      printf
9826    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9827    bx      lr
9828
9829/*
9830 * Print a newline, preserving registers.
9831 */
9832common_printNewline:
9833    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9834    ldr     r0, strNewline
9835    bl      printf
9836    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9837    bx      lr
9838
9839    /*
9840     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9841     */
9842common_printHex:
9843    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9844    mov     r1, r0
9845    ldr     r0, strPrintHex
9846    bl      printf
9847    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9848    bx      lr
9849
9850/*
9851 * Print the 64-bit quantity in r0-r1, preserving registers.
9852 */
9853common_printLong:
9854    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9855    mov     r3, r1
9856    mov     r2, r0
9857    ldr     r0, strPrintLong
9858    bl      printf
9859    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9860    bx      lr
9861
9862/*
9863 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9864 */
9865common_printMethod:
9866    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9867    bl      dvmMterpPrintMethod
9868    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9869    bx      lr
9870
9871/*
9872 * Call a C helper function that dumps regs and possibly some
9873 * additional info.  Requires the C function to be compiled in.
9874 */
9875    .if     0
9876common_dumpRegs:
9877    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9878    bl      dvmMterpDumpArmRegs
9879    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9880    bx      lr
9881    .endif
9882
9883#if 0
9884/*
9885 * Experiment on VFP mode.
9886 *
9887 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
9888 *
9889 * Updates the bits specified by "mask", setting them to the values in "val".
9890 */
9891setFPSCR:
9892    and     r0, r0, r1                  @ make sure no stray bits are set
9893    fmrx    r2, fpscr                   @ get VFP reg
9894    mvn     r1, r1                      @ bit-invert mask
9895    and     r2, r2, r1                  @ clear masked bits
9896    orr     r2, r2, r0                  @ set specified bits
9897    fmxr    fpscr, r2                   @ set VFP reg
9898    mov     r0, r2                      @ return new value
9899    bx      lr
9900
9901    .align  2
9902    .global dvmConfigureFP
9903    .type   dvmConfigureFP, %function
9904dvmConfigureFP:
9905    stmfd   sp!, {ip, lr}
9906    /* 0x03000000 sets DN/FZ */
9907    /* 0x00009f00 clears the six exception enable flags */
9908    bl      common_squeak0
9909    mov     r0, #0x03000000             @ r0<- 0x03000000
9910    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
9911    bl      setFPSCR
9912    ldmfd   sp!, {ip, pc}
9913#endif
9914
9915
9916/*
9917 * String references, must be close to the code that uses them.
9918 */
9919    .align  2
9920strArithmeticException:
9921    .word   .LstrArithmeticException
9922strArrayIndexException:
9923    .word   .LstrArrayIndexException
9924strArrayStoreException:
9925    .word   .LstrArrayStoreException
9926strDivideByZero:
9927    .word   .LstrDivideByZero
9928strNegativeArraySizeException:
9929    .word   .LstrNegativeArraySizeException
9930strNoSuchMethodError:
9931    .word   .LstrNoSuchMethodError
9932strNullPointerException:
9933    .word   .LstrNullPointerException
9934
9935strLogTag:
9936    .word   .LstrLogTag
9937strExceptionNotCaughtLocally:
9938    .word   .LstrExceptionNotCaughtLocally
9939
9940strNewline:
9941    .word   .LstrNewline
9942strSqueak:
9943    .word   .LstrSqueak
9944strPrintHex:
9945    .word   .LstrPrintHex
9946strPrintLong:
9947    .word   .LstrPrintLong
9948
9949/*
9950 * Zero-terminated ASCII string data.
9951 *
9952 * On ARM we have two choices: do like gcc does, and LDR from a .word
9953 * with the address, or use an ADR pseudo-op to get the address
9954 * directly.  ADR saves 4 bytes and an indirection, but it's using a
9955 * PC-relative addressing mode and hence has a limited range, which
9956 * makes it not work well with mergeable string sections.
9957 */
9958    .section .rodata.str1.4,"aMS",%progbits,1
9959
9960.LstrBadEntryPoint:
9961    .asciz  "Bad entry point %d\n"
9962.LstrArithmeticException:
9963    .asciz  "Ljava/lang/ArithmeticException;"
9964.LstrArrayIndexException:
9965    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9966.LstrArrayStoreException:
9967    .asciz  "Ljava/lang/ArrayStoreException;"
9968.LstrClassCastException:
9969    .asciz  "Ljava/lang/ClassCastException;"
9970.LstrDivideByZero:
9971    .asciz  "divide by zero"
9972.LstrFilledNewArrayNotImpl:
9973    .asciz  "filled-new-array only implemented for objects and 'int'"
9974.LstrInternalError:
9975    .asciz  "Ljava/lang/InternalError;"
9976.LstrInstantiationError:
9977    .asciz  "Ljava/lang/InstantiationError;"
9978.LstrNegativeArraySizeException:
9979    .asciz  "Ljava/lang/NegativeArraySizeException;"
9980.LstrNoSuchMethodError:
9981    .asciz  "Ljava/lang/NoSuchMethodError;"
9982.LstrNullPointerException:
9983    .asciz  "Ljava/lang/NullPointerException;"
9984
9985.LstrLogTag:
9986    .asciz  "mterp"
9987.LstrExceptionNotCaughtLocally:
9988    .asciz  "Exception %s from %s:%d not caught locally\n"
9989
9990.LstrNewline:
9991    .asciz  "\n"
9992.LstrSqueak:
9993    .asciz  "<%d>"
9994.LstrPrintHex:
9995    .asciz  "<0x%x>"
9996.LstrPrintLong:
9997    .asciz  "<%lld>"
9998
9999
10000