InterpAsm-armv5te-vfp.S revision 7a0bcd0de6c4da6499a088a18d1750e51204c2a6
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
189#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204
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    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
315    /* Entry is always a possible trace start */
316    GET_JIT_PROF_TABLE(r0)
317    FETCH_INST()
318    mov    r1, #0                       @ prepare the value for the new state
319    str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
320    cmp    r0,#0
321    bne    common_updateProfile
322    GET_INST_OPCODE(ip)
323    GOTO_OPCODE(ip)
324#else
325    /* start executing the instruction at rPC */
326    FETCH_INST()                        @ load rINST from rPC
327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
328    GOTO_OPCODE(ip)                     @ jump to next instruction
329#endif
330
331.Lnot_instr:
332    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
333    beq     common_returnFromMethod
334
335.Lnot_return:
336    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
337    beq     common_exceptionThrown
338
339#if defined(WITH_JIT)
340.Lnot_throw:
341    ldr     r0,[rGLUE, #offGlue_jitResume]
342    ldr     r2,[rGLUE, #offGlue_jitResumePC]
343    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
344    bne     .Lbad_arg
345    cmp     rPC,r2
346    bne     .Lno_singleStep             @ must have branched, don't resume
347    mov     r1, #kInterpEntryInstr
348    strb    r1, [rGLUE, #offGlue_entryPoint]
349    ldr     rINST, .LdvmCompilerTemplate
350    bx      r0                          @ re-enter the translation
351.LdvmCompilerTemplate:
352    .word   dvmCompilerTemplateStart
353#endif
354
355.Lbad_arg:
356    ldr     r0, strBadEntryPoint
357    @ r1 holds value of entryPoint
358    bl      printf
359    bl      dvmAbort
360    .fnend
361
362
363    .global dvmMterpStdBail
364    .type   dvmMterpStdBail, %function
365
366/*
367 * Restore the stack pointer and PC from the save point established on entry.
368 * This is essentially the same as a longjmp, but should be cheaper.  The
369 * last instruction causes us to return to whoever called dvmMterpStdRun.
370 *
371 * We pushed some registers on the stack in dvmMterpStdRun, then saved
372 * SP and LR.  Here we restore SP, restore the registers, and then restore
373 * LR to PC.
374 *
375 * On entry:
376 *  r0  MterpGlue* glue
377 *  r1  bool changeInterp
378 */
379dvmMterpStdBail:
380    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
381    mov     r0, r1                          @ return the changeInterp value
382    add     sp, sp, #4                      @ un-align 64
383    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
384
385
386/*
387 * String references.
388 */
389strBadEntryPoint:
390    .word   .LstrBadEntryPoint
391
392
393
394    .global dvmAsmInstructionStart
395    .type   dvmAsmInstructionStart, %function
396dvmAsmInstructionStart = .L_OP_NOP
397    .text
398
399/* ------------------------------ */
400    .balign 64
401.L_OP_NOP: /* 0x00 */
402/* File: armv5te/OP_NOP.S */
403    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
404    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
405    GOTO_OPCODE(ip)                     @ execute it
406
407#ifdef ASSIST_DEBUGGER
408    /* insert fake function header to help gdb find the stack frame */
409    .type   dalvik_inst, %function
410dalvik_inst:
411    .fnstart
412    MTERP_ENTRY1
413    MTERP_ENTRY2
414    .fnend
415#endif
416
417
418/* ------------------------------ */
419    .balign 64
420.L_OP_MOVE: /* 0x01 */
421/* File: armv5te/OP_MOVE.S */
422    /* for move, move-object, long-to-int */
423    /* op vA, vB */
424    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
425    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
426    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
427    GET_VREG(r2, r1)                    @ r2<- fp[B]
428    and     r0, r0, #15
429    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
430    SET_VREG(r2, r0)                    @ fp[A]<- r2
431    GOTO_OPCODE(ip)                     @ execute next instruction
432
433
434/* ------------------------------ */
435    .balign 64
436.L_OP_MOVE_FROM16: /* 0x02 */
437/* File: armv5te/OP_MOVE_FROM16.S */
438    /* for: move/from16, move-object/from16 */
439    /* op vAA, vBBBB */
440    FETCH(r1, 1)                        @ r1<- BBBB
441    mov     r0, rINST, lsr #8           @ r0<- AA
442    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
443    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
444    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
445    SET_VREG(r2, r0)                    @ fp[AA]<- r2
446    GOTO_OPCODE(ip)                     @ jump to next instruction
447
448
449/* ------------------------------ */
450    .balign 64
451.L_OP_MOVE_16: /* 0x03 */
452/* File: armv5te/OP_MOVE_16.S */
453    /* for: move/16, move-object/16 */
454    /* op vAAAA, vBBBB */
455    FETCH(r1, 2)                        @ r1<- BBBB
456    FETCH(r0, 1)                        @ r0<- AAAA
457    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
458    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
459    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
460    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
461    GOTO_OPCODE(ip)                     @ jump to next instruction
462
463
464/* ------------------------------ */
465    .balign 64
466.L_OP_MOVE_WIDE: /* 0x04 */
467/* File: armv5te/OP_MOVE_WIDE.S */
468    /* move-wide vA, vB */
469    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
470    mov     r2, rINST, lsr #8           @ r2<- A(+)
471    mov     r3, rINST, lsr #12          @ r3<- B
472    and     r2, r2, #15
473    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
474    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
475    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
476    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
477    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
478    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
479    GOTO_OPCODE(ip)                     @ jump to next instruction
480
481
482/* ------------------------------ */
483    .balign 64
484.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
485/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
486    /* move-wide/from16 vAA, vBBBB */
487    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
488    FETCH(r3, 1)                        @ r3<- BBBB
489    mov     r2, rINST, lsr #8           @ r2<- AA
490    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
491    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
492    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
493    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
494    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
495    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
496    GOTO_OPCODE(ip)                     @ jump to next instruction
497
498
499/* ------------------------------ */
500    .balign 64
501.L_OP_MOVE_WIDE_16: /* 0x06 */
502/* File: armv5te/OP_MOVE_WIDE_16.S */
503    /* move-wide/16 vAAAA, vBBBB */
504    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
505    FETCH(r3, 2)                        @ r3<- BBBB
506    FETCH(r2, 1)                        @ r2<- AAAA
507    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
508    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
509    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
510    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
512    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
513    GOTO_OPCODE(ip)                     @ jump to next instruction
514
515
516/* ------------------------------ */
517    .balign 64
518.L_OP_MOVE_OBJECT: /* 0x07 */
519/* File: armv5te/OP_MOVE_OBJECT.S */
520/* File: armv5te/OP_MOVE.S */
521    /* for move, move-object, long-to-int */
522    /* op vA, vB */
523    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
524    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
525    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
526    GET_VREG(r2, r1)                    @ r2<- fp[B]
527    and     r0, r0, #15
528    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
529    SET_VREG(r2, r0)                    @ fp[A]<- r2
530    GOTO_OPCODE(ip)                     @ execute next instruction
531
532
533
534/* ------------------------------ */
535    .balign 64
536.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
537/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
538/* File: armv5te/OP_MOVE_FROM16.S */
539    /* for: move/from16, move-object/from16 */
540    /* op vAA, vBBBB */
541    FETCH(r1, 1)                        @ r1<- BBBB
542    mov     r0, rINST, lsr #8           @ r0<- AA
543    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
544    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
545    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
546    SET_VREG(r2, r0)                    @ fp[AA]<- r2
547    GOTO_OPCODE(ip)                     @ jump to next instruction
548
549
550
551/* ------------------------------ */
552    .balign 64
553.L_OP_MOVE_OBJECT_16: /* 0x09 */
554/* File: armv5te/OP_MOVE_OBJECT_16.S */
555/* File: armv5te/OP_MOVE_16.S */
556    /* for: move/16, move-object/16 */
557    /* op vAAAA, vBBBB */
558    FETCH(r1, 2)                        @ r1<- BBBB
559    FETCH(r0, 1)                        @ r0<- AAAA
560    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
561    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
562    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
563    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
564    GOTO_OPCODE(ip)                     @ jump to next instruction
565
566
567
568/* ------------------------------ */
569    .balign 64
570.L_OP_MOVE_RESULT: /* 0x0a */
571/* File: armv5te/OP_MOVE_RESULT.S */
572    /* for: move-result, move-result-object */
573    /* op vAA */
574    mov     r2, rINST, lsr #8           @ r2<- AA
575    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
576    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
577    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
578    SET_VREG(r0, r2)                    @ fp[AA]<- r0
579    GOTO_OPCODE(ip)                     @ jump to next instruction
580
581
582/* ------------------------------ */
583    .balign 64
584.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
585/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
586    /* move-result-wide vAA */
587    mov     r2, rINST, lsr #8           @ r2<- AA
588    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
589    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
590    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
591    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
592    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
593    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
594    GOTO_OPCODE(ip)                     @ jump to next instruction
595
596
597/* ------------------------------ */
598    .balign 64
599.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
600/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
601/* File: armv5te/OP_MOVE_RESULT.S */
602    /* for: move-result, move-result-object */
603    /* op vAA */
604    mov     r2, rINST, lsr #8           @ r2<- AA
605    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
606    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
608    SET_VREG(r0, r2)                    @ fp[AA]<- r0
609    GOTO_OPCODE(ip)                     @ jump to next instruction
610
611
612
613/* ------------------------------ */
614    .balign 64
615.L_OP_MOVE_EXCEPTION: /* 0x0d */
616/* File: armv5te/OP_MOVE_EXCEPTION.S */
617    /* move-exception vAA */
618    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
619    mov     r2, rINST, lsr #8           @ r2<- AA
620    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
621    mov     r1, #0                      @ r1<- 0
622    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
623    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
625    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
626    GOTO_OPCODE(ip)                     @ jump to next instruction
627
628
629/* ------------------------------ */
630    .balign 64
631.L_OP_RETURN_VOID: /* 0x0e */
632/* File: armv5te/OP_RETURN_VOID.S */
633    b       common_returnFromMethod
634
635
636/* ------------------------------ */
637    .balign 64
638.L_OP_RETURN: /* 0x0f */
639/* File: armv5te/OP_RETURN.S */
640    /*
641     * Return a 32-bit value.  Copies the return value into the "glue"
642     * structure, then jumps to the return handler.
643     *
644     * for: return, return-object
645     */
646    /* op vAA */
647    mov     r2, rINST, lsr #8           @ r2<- AA
648    GET_VREG(r0, r2)                    @ r0<- vAA
649    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
650    b       common_returnFromMethod
651
652
653/* ------------------------------ */
654    .balign 64
655.L_OP_RETURN_WIDE: /* 0x10 */
656/* File: armv5te/OP_RETURN_WIDE.S */
657    /*
658     * Return a 64-bit value.  Copies the return value into the "glue"
659     * structure, then jumps to the return handler.
660     */
661    /* return-wide vAA */
662    mov     r2, rINST, lsr #8           @ r2<- AA
663    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
664    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
665    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
666    stmia   r3, {r0-r1}                 @ retval<- r0/r1
667    b       common_returnFromMethod
668
669
670/* ------------------------------ */
671    .balign 64
672.L_OP_RETURN_OBJECT: /* 0x11 */
673/* File: armv5te/OP_RETURN_OBJECT.S */
674/* File: armv5te/OP_RETURN.S */
675    /*
676     * Return a 32-bit value.  Copies the return value into the "glue"
677     * structure, then jumps to the return handler.
678     *
679     * for: return, return-object
680     */
681    /* op vAA */
682    mov     r2, rINST, lsr #8           @ r2<- AA
683    GET_VREG(r0, r2)                    @ r0<- vAA
684    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
685    b       common_returnFromMethod
686
687
688
689/* ------------------------------ */
690    .balign 64
691.L_OP_CONST_4: /* 0x12 */
692/* File: armv5te/OP_CONST_4.S */
693    /* const/4 vA, #+B */
694    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
695    mov     r0, rINST, lsr #8           @ r0<- A+
696    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
697    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
698    and     r0, r0, #15
699    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
700    SET_VREG(r1, r0)                    @ fp[A]<- r1
701    GOTO_OPCODE(ip)                     @ execute next instruction
702
703
704/* ------------------------------ */
705    .balign 64
706.L_OP_CONST_16: /* 0x13 */
707/* File: armv5te/OP_CONST_16.S */
708    /* const/16 vAA, #+BBBB */
709    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
710    mov     r3, rINST, lsr #8           @ r3<- AA
711    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
712    SET_VREG(r0, r3)                    @ vAA<- r0
713    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
714    GOTO_OPCODE(ip)                     @ jump to next instruction
715
716
717/* ------------------------------ */
718    .balign 64
719.L_OP_CONST: /* 0x14 */
720/* File: armv5te/OP_CONST.S */
721    /* const vAA, #+BBBBbbbb */
722    mov     r3, rINST, lsr #8           @ r3<- AA
723    FETCH(r0, 1)                        @ r0<- bbbb (low)
724    FETCH(r1, 2)                        @ r1<- BBBB (high)
725    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
726    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
728    SET_VREG(r0, r3)                    @ vAA<- r0
729    GOTO_OPCODE(ip)                     @ jump to next instruction
730
731
732/* ------------------------------ */
733    .balign 64
734.L_OP_CONST_HIGH16: /* 0x15 */
735/* File: armv5te/OP_CONST_HIGH16.S */
736    /* const/high16 vAA, #+BBBB0000 */
737    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
738    mov     r3, rINST, lsr #8           @ r3<- AA
739    mov     r0, r0, lsl #16             @ r0<- BBBB0000
740    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
741    SET_VREG(r0, r3)                    @ vAA<- r0
742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
743    GOTO_OPCODE(ip)                     @ jump to next instruction
744
745
746/* ------------------------------ */
747    .balign 64
748.L_OP_CONST_WIDE_16: /* 0x16 */
749/* File: armv5te/OP_CONST_WIDE_16.S */
750    /* const-wide/16 vAA, #+BBBB */
751    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
752    mov     r3, rINST, lsr #8           @ r3<- AA
753    mov     r1, r0, asr #31             @ r1<- ssssssss
754    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
755    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
757    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
758    GOTO_OPCODE(ip)                     @ jump to next instruction
759
760
761/* ------------------------------ */
762    .balign 64
763.L_OP_CONST_WIDE_32: /* 0x17 */
764/* File: armv5te/OP_CONST_WIDE_32.S */
765    /* const-wide/32 vAA, #+BBBBbbbb */
766    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
767    mov     r3, rINST, lsr #8           @ r3<- AA
768    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
769    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
770    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
771    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
772    mov     r1, r0, asr #31             @ r1<- ssssssss
773    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
774    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
775    GOTO_OPCODE(ip)                     @ jump to next instruction
776
777
778/* ------------------------------ */
779    .balign 64
780.L_OP_CONST_WIDE: /* 0x18 */
781/* File: armv5te/OP_CONST_WIDE.S */
782    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
783    FETCH(r0, 1)                        @ r0<- bbbb (low)
784    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
785    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
786    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
787    FETCH(r3, 4)                        @ r3<- HHHH (high)
788    mov     r9, rINST, lsr #8           @ r9<- AA
789    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
790    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
791    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
793    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
794    GOTO_OPCODE(ip)                     @ jump to next instruction
795
796
797/* ------------------------------ */
798    .balign 64
799.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
800/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
801    /* const-wide/high16 vAA, #+BBBB000000000000 */
802    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
803    mov     r3, rINST, lsr #8           @ r3<- AA
804    mov     r0, #0                      @ r0<- 00000000
805    mov     r1, r1, lsl #16             @ r1<- BBBB0000
806    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
807    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
809    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
810    GOTO_OPCODE(ip)                     @ jump to next instruction
811
812
813/* ------------------------------ */
814    .balign 64
815.L_OP_CONST_STRING: /* 0x1a */
816/* File: armv5te/OP_CONST_STRING.S */
817    /* const/string vAA, String@BBBB */
818    FETCH(r1, 1)                        @ r1<- BBBB
819    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
820    mov     r9, rINST, lsr #8           @ r9<- AA
821    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
822    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
823    cmp     r0, #0                      @ not yet resolved?
824    beq     .LOP_CONST_STRING_resolve
825    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
827    SET_VREG(r0, r9)                    @ vAA<- r0
828    GOTO_OPCODE(ip)                     @ jump to next instruction
829
830/* ------------------------------ */
831    .balign 64
832.L_OP_CONST_STRING_JUMBO: /* 0x1b */
833/* File: armv5te/OP_CONST_STRING_JUMBO.S */
834    /* const/string vAA, String@BBBBBBBB */
835    FETCH(r0, 1)                        @ r0<- bbbb (low)
836    FETCH(r1, 2)                        @ r1<- BBBB (high)
837    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
838    mov     r9, rINST, lsr #8           @ r9<- AA
839    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
840    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
841    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
842    cmp     r0, #0
843    beq     .LOP_CONST_STRING_JUMBO_resolve
844    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
846    SET_VREG(r0, r9)                    @ vAA<- r0
847    GOTO_OPCODE(ip)                     @ jump to next instruction
848
849/* ------------------------------ */
850    .balign 64
851.L_OP_CONST_CLASS: /* 0x1c */
852/* File: armv5te/OP_CONST_CLASS.S */
853    /* const/class vAA, Class@BBBB */
854    FETCH(r1, 1)                        @ r1<- BBBB
855    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
856    mov     r9, rINST, lsr #8           @ r9<- AA
857    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
858    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
859    cmp     r0, #0                      @ not yet resolved?
860    beq     .LOP_CONST_CLASS_resolve
861    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
863    SET_VREG(r0, r9)                    @ vAA<- r0
864    GOTO_OPCODE(ip)                     @ jump to next instruction
865
866/* ------------------------------ */
867    .balign 64
868.L_OP_MONITOR_ENTER: /* 0x1d */
869/* File: armv5te/OP_MONITOR_ENTER.S */
870    /*
871     * Synchronize on an object.
872     */
873    /* monitor-enter vAA */
874    mov     r2, rINST, lsr #8           @ r2<- AA
875    GET_VREG(r1, r2)                    @ r1<- vAA (object)
876    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
877    cmp     r1, #0                      @ null object?
878    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
879    beq     common_errNullObject        @ null object, throw an exception
880    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
881    bl      dvmLockObject               @ call(self, obj)
882#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
883    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
884    ldr     r1, [r0, #offThread_exception] @ check for exception
885    cmp     r1, #0
886    bne     common_exceptionThrown      @ exception raised, bail out
887#endif
888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
889    GOTO_OPCODE(ip)                     @ jump to next instruction
890
891
892/* ------------------------------ */
893    .balign 64
894.L_OP_MONITOR_EXIT: /* 0x1e */
895/* File: armv5te/OP_MONITOR_EXIT.S */
896    /*
897     * Unlock an object.
898     *
899     * Exceptions that occur when unlocking a monitor need to appear as
900     * if they happened at the following instruction.  See the Dalvik
901     * instruction spec.
902     */
903    /* monitor-exit vAA */
904    mov     r2, rINST, lsr #8           @ r2<- AA
905    EXPORT_PC()                         @ before fetch: export the PC
906    GET_VREG(r1, r2)                    @ r1<- vAA (object)
907    cmp     r1, #0                      @ null object?
908    beq     common_errNullObject        @ yes
909    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
910    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
911    cmp     r0, #0                      @ failed?
912    beq     common_exceptionThrown      @ yes, exception is pending
913    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
914    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
915    GOTO_OPCODE(ip)                     @ jump to next instruction
916
917
918/* ------------------------------ */
919    .balign 64
920.L_OP_CHECK_CAST: /* 0x1f */
921/* File: armv5te/OP_CHECK_CAST.S */
922    /*
923     * Check to see if a cast from one class to another is allowed.
924     */
925    /* check-cast vAA, class@BBBB */
926    mov     r3, rINST, lsr #8           @ r3<- AA
927    FETCH(r2, 1)                        @ r2<- BBBB
928    GET_VREG(r9, r3)                    @ r9<- object
929    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
930    cmp     r9, #0                      @ is object null?
931    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
932    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
933    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
934    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
935    cmp     r1, #0                      @ have we resolved this before?
936    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
937.LOP_CHECK_CAST_resolved:
938    cmp     r0, r1                      @ same class (trivial success)?
939    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
940.LOP_CHECK_CAST_okay:
941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
942    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
943    GOTO_OPCODE(ip)                     @ jump to next instruction
944
945/* ------------------------------ */
946    .balign 64
947.L_OP_INSTANCE_OF: /* 0x20 */
948/* File: armv5te/OP_INSTANCE_OF.S */
949    /*
950     * Check to see if an object reference is an instance of a class.
951     *
952     * Most common situation is a non-null object, being compared against
953     * an already-resolved class.
954     */
955    /* instance-of vA, vB, class@CCCC */
956    mov     r3, rINST, lsr #12          @ r3<- B
957    mov     r9, rINST, lsr #8           @ r9<- A+
958    GET_VREG(r0, r3)                    @ r0<- vB (object)
959    and     r9, r9, #15                 @ r9<- A
960    cmp     r0, #0                      @ is object null?
961    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
962    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
963    FETCH(r3, 1)                        @ r3<- CCCC
964    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
965    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
966    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
967    cmp     r1, #0                      @ have we resolved this before?
968    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
969.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
970    cmp     r0, r1                      @ same class (trivial success)?
971    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
972    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
973
974/* ------------------------------ */
975    .balign 64
976.L_OP_ARRAY_LENGTH: /* 0x21 */
977/* File: armv5te/OP_ARRAY_LENGTH.S */
978    /*
979     * Return the length of an array.
980     */
981    mov     r1, rINST, lsr #12          @ r1<- B
982    mov     r2, rINST, lsr #8           @ r2<- A+
983    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
984    and     r2, r2, #15                 @ r2<- A
985    cmp     r0, #0                      @ is object null?
986    beq     common_errNullObject        @ yup, fail
987    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
988    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
989    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
990    SET_VREG(r3, r2)                    @ vB<- length
991    GOTO_OPCODE(ip)                     @ jump to next instruction
992
993
994/* ------------------------------ */
995    .balign 64
996.L_OP_NEW_INSTANCE: /* 0x22 */
997/* File: armv5te/OP_NEW_INSTANCE.S */
998    /*
999     * Create a new instance of a class.
1000     */
1001    /* new-instance vAA, class@BBBB */
1002    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1003    FETCH(r1, 1)                        @ r1<- BBBB
1004    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1005    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1006    EXPORT_PC()                         @ req'd for init, resolve, alloc
1007    cmp     r0, #0                      @ already resolved?
1008    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1009.LOP_NEW_INSTANCE_resolved:   @ r0=class
1010    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1011    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1012    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1013.LOP_NEW_INSTANCE_initialized: @ r0=class
1014    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1015    bl      dvmAllocObject              @ r0<- new object
1016    b       .LOP_NEW_INSTANCE_finish          @ continue
1017
1018/* ------------------------------ */
1019    .balign 64
1020.L_OP_NEW_ARRAY: /* 0x23 */
1021/* File: armv5te/OP_NEW_ARRAY.S */
1022    /*
1023     * Allocate an array of objects, specified with the array class
1024     * and a count.
1025     *
1026     * The verifier guarantees that this is an array class, so we don't
1027     * check for it here.
1028     */
1029    /* new-array vA, vB, class@CCCC */
1030    mov     r0, rINST, lsr #12          @ r0<- B
1031    FETCH(r2, 1)                        @ r2<- CCCC
1032    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1033    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1034    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1035    cmp     r1, #0                      @ check length
1036    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1037    bmi     common_errNegativeArraySize @ negative length, bail
1038    cmp     r0, #0                      @ already resolved?
1039    EXPORT_PC()                         @ req'd for resolve, alloc
1040    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1041    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1042
1043/* ------------------------------ */
1044    .balign 64
1045.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1046/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1047    /*
1048     * Create a new array with elements filled from registers.
1049     *
1050     * for: filled-new-array, filled-new-array/range
1051     */
1052    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1053    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1054    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1055    FETCH(r1, 1)                        @ r1<- BBBB
1056    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1057    EXPORT_PC()                         @ need for resolve and alloc
1058    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1059    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1060    cmp     r0, #0                      @ already resolved?
1061    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10628:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1063    mov     r2, #0                      @ r2<- false
1064    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1065    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1066    cmp     r0, #0                      @ got null?
1067    beq     common_exceptionThrown      @ yes, handle exception
1068    b       .LOP_FILLED_NEW_ARRAY_continue
1069
1070/* ------------------------------ */
1071    .balign 64
1072.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1073/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1074/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1075    /*
1076     * Create a new array with elements filled from registers.
1077     *
1078     * for: filled-new-array, filled-new-array/range
1079     */
1080    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1081    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1082    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1083    FETCH(r1, 1)                        @ r1<- BBBB
1084    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1085    EXPORT_PC()                         @ need for resolve and alloc
1086    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1087    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1088    cmp     r0, #0                      @ already resolved?
1089    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10908:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1091    mov     r2, #0                      @ r2<- false
1092    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1093    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1094    cmp     r0, #0                      @ got null?
1095    beq     common_exceptionThrown      @ yes, handle exception
1096    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1097
1098
1099/* ------------------------------ */
1100    .balign 64
1101.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1102/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1103    /* fill-array-data vAA, +BBBBBBBB */
1104    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1105    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1106    mov     r3, rINST, lsr #8           @ r3<- AA
1107    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1108    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1109    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1110    EXPORT_PC();
1111    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1112    cmp     r0, #0                      @ 0 means an exception is thrown
1113    beq     common_exceptionThrown      @ has exception
1114    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1116    GOTO_OPCODE(ip)                     @ jump to next instruction
1117
1118/* ------------------------------ */
1119    .balign 64
1120.L_OP_THROW: /* 0x27 */
1121/* File: armv5te/OP_THROW.S */
1122    /*
1123     * Throw an exception object in the current thread.
1124     */
1125    /* throw vAA */
1126    mov     r2, rINST, lsr #8           @ r2<- AA
1127    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1128    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1129    cmp     r1, #0                      @ null object?
1130    beq     common_errNullObject        @ yes, throw an NPE instead
1131    @ bypass dvmSetException, just store it
1132    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1133    b       common_exceptionThrown
1134
1135
1136/* ------------------------------ */
1137    .balign 64
1138.L_OP_GOTO: /* 0x28 */
1139/* File: armv5te/OP_GOTO.S */
1140    /*
1141     * Unconditional branch, 8-bit offset.
1142     *
1143     * The branch distance is a signed code-unit offset, which we need to
1144     * double to get a byte offset.
1145     */
1146    /* goto +AA */
1147    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1148    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1149    mov     r9, r9, lsl #1              @ r9<- byte offset
1150    bmi     common_backwardBranch       @ backward branch, do periodic checks
1151#if defined(WITH_JIT)
1152    GET_JIT_PROF_TABLE(r0)
1153    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1154    cmp     r0,#0
1155    bne     common_updateProfile
1156    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1157    GOTO_OPCODE(ip)                     @ jump to next instruction
1158#else
1159    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1160    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1161    GOTO_OPCODE(ip)                     @ jump to next instruction
1162#endif
1163
1164/* ------------------------------ */
1165    .balign 64
1166.L_OP_GOTO_16: /* 0x29 */
1167/* File: armv5te/OP_GOTO_16.S */
1168    /*
1169     * Unconditional branch, 16-bit offset.
1170     *
1171     * The branch distance is a signed code-unit offset, which we need to
1172     * double to get a byte offset.
1173     */
1174    /* goto/16 +AAAA */
1175    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1176    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1177    bmi     common_backwardBranch       @ backward branch, do periodic checks
1178#if defined(WITH_JIT)
1179    GET_JIT_PROF_TABLE(r0)
1180    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1181    cmp     r0,#0
1182    bne     common_updateProfile
1183    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1184    GOTO_OPCODE(ip)                     @ jump to next instruction
1185#else
1186    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1187    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1188    GOTO_OPCODE(ip)                     @ jump to next instruction
1189#endif
1190
1191
1192/* ------------------------------ */
1193    .balign 64
1194.L_OP_GOTO_32: /* 0x2a */
1195/* File: armv5te/OP_GOTO_32.S */
1196    /*
1197     * Unconditional branch, 32-bit offset.
1198     *
1199     * The branch distance is a signed code-unit offset, which we need to
1200     * double to get a byte offset.
1201     *
1202     * Unlike most opcodes, this one is allowed to branch to itself, so
1203     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1204     * instruction doesn't affect the V flag, so we need to clear it
1205     * explicitly.
1206     */
1207    /* goto/32 +AAAAAAAA */
1208    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1209    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1210    cmp     ip, ip                      @ (clear V flag during stall)
1211    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1212    mov     r9, r0, asl #1              @ r9<- byte offset
1213    ble     common_backwardBranch       @ backward branch, do periodic checks
1214#if defined(WITH_JIT)
1215    GET_JIT_PROF_TABLE(r0)
1216    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1217    cmp     r0,#0
1218    bne     common_updateProfile
1219    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1220    GOTO_OPCODE(ip)                     @ jump to next instruction
1221#else
1222    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1223    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1224    GOTO_OPCODE(ip)                     @ jump to next instruction
1225#endif
1226
1227/* ------------------------------ */
1228    .balign 64
1229.L_OP_PACKED_SWITCH: /* 0x2b */
1230/* File: armv5te/OP_PACKED_SWITCH.S */
1231    /*
1232     * Handle a packed-switch or sparse-switch instruction.  In both cases
1233     * we decode it and hand it off to a helper function.
1234     *
1235     * We don't really expect backward branches in a switch statement, but
1236     * they're perfectly legal, so we check for them here.
1237     *
1238     * for: packed-switch, sparse-switch
1239     */
1240    /* op vAA, +BBBB */
1241    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1242    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1243    mov     r3, rINST, lsr #8           @ r3<- AA
1244    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1245    GET_VREG(r1, r3)                    @ r1<- vAA
1246    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1247    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1248    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1249    bmi     common_backwardBranch       @ backward branch, do periodic checks
1250    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1251#if defined(WITH_JIT)
1252    GET_JIT_PROF_TABLE(r0)
1253    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1254    cmp     r0,#0
1255    bne     common_updateProfile
1256    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1257    GOTO_OPCODE(ip)                     @ jump to next instruction
1258#else
1259    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1260    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1261    GOTO_OPCODE(ip)                     @ jump to next instruction
1262#endif
1263
1264
1265/* ------------------------------ */
1266    .balign 64
1267.L_OP_SPARSE_SWITCH: /* 0x2c */
1268/* File: armv5te/OP_SPARSE_SWITCH.S */
1269/* File: armv5te/OP_PACKED_SWITCH.S */
1270    /*
1271     * Handle a packed-switch or sparse-switch instruction.  In both cases
1272     * we decode it and hand it off to a helper function.
1273     *
1274     * We don't really expect backward branches in a switch statement, but
1275     * they're perfectly legal, so we check for them here.
1276     *
1277     * for: packed-switch, sparse-switch
1278     */
1279    /* op vAA, +BBBB */
1280    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1281    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1282    mov     r3, rINST, lsr #8           @ r3<- AA
1283    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1284    GET_VREG(r1, r3)                    @ r1<- vAA
1285    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1286    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1287    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1288    bmi     common_backwardBranch       @ backward branch, do periodic checks
1289    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1290#if defined(WITH_JIT)
1291    GET_JIT_PROF_TABLE(r0)
1292    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1293    cmp     r0,#0
1294    bne     common_updateProfile
1295    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1296    GOTO_OPCODE(ip)                     @ jump to next instruction
1297#else
1298    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1299    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1300    GOTO_OPCODE(ip)                     @ jump to next instruction
1301#endif
1302
1303
1304
1305/* ------------------------------ */
1306    .balign 64
1307.L_OP_CMPL_FLOAT: /* 0x2d */
1308/* File: arm-vfp/OP_CMPL_FLOAT.S */
1309    /*
1310     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1311     * destination register based on the results of the comparison.
1312     *
1313     * int compare(x, y) {
1314     *     if (x == y) {
1315     *         return 0;
1316     *     } else if (x > y) {
1317     *         return 1;
1318     *     } else if (x < y) {
1319     *         return -1;
1320     *     } else {
1321     *         return -1;
1322     *     }
1323     * }
1324     */
1325    /* op vAA, vBB, vCC */
1326    FETCH(r0, 1)                        @ r0<- CCBB
1327    mov     r9, rINST, lsr #8           @ r9<- AA
1328    and     r2, r0, #255                @ r2<- BB
1329    mov     r3, r0, lsr #8              @ r3<- CC
1330    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1331    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1332    flds    s0, [r2]                    @ s0<- vBB
1333    flds    s1, [r3]                    @ s1<- vCC
1334    fcmpes  s0, s1                      @ compare (vBB, vCC)
1335    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1336    mvn     r0, #0                      @ r0<- -1 (default)
1337    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1338    fmstat                              @ export status flags
1339    movgt   r0, #1                      @ (greater than) r1<- 1
1340    moveq   r0, #0                      @ (equal) r1<- 0
1341    b       .LOP_CMPL_FLOAT_finish          @ argh
1342
1343
1344/* ------------------------------ */
1345    .balign 64
1346.L_OP_CMPG_FLOAT: /* 0x2e */
1347/* File: arm-vfp/OP_CMPG_FLOAT.S */
1348    /*
1349     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1350     * destination register based on the results of the comparison.
1351     *
1352     * int compare(x, y) {
1353     *     if (x == y) {
1354     *         return 0;
1355     *     } else if (x < y) {
1356     *         return -1;
1357     *     } else if (x > y) {
1358     *         return 1;
1359     *     } else {
1360     *         return 1;
1361     *     }
1362     * }
1363     */
1364    /* op vAA, vBB, vCC */
1365    FETCH(r0, 1)                        @ r0<- CCBB
1366    mov     r9, rINST, lsr #8           @ r9<- AA
1367    and     r2, r0, #255                @ r2<- BB
1368    mov     r3, r0, lsr #8              @ r3<- CC
1369    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1370    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1371    flds    s0, [r2]                    @ s0<- vBB
1372    flds    s1, [r3]                    @ s1<- vCC
1373    fcmpes  s0, s1                      @ compare (vBB, vCC)
1374    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1375    mov     r0, #1                      @ r0<- 1 (default)
1376    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1377    fmstat                              @ export status flags
1378    mvnmi   r0, #0                      @ (less than) r1<- -1
1379    moveq   r0, #0                      @ (equal) r1<- 0
1380    b       .LOP_CMPG_FLOAT_finish          @ argh
1381
1382
1383/* ------------------------------ */
1384    .balign 64
1385.L_OP_CMPL_DOUBLE: /* 0x2f */
1386/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1387    /*
1388     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1389     * destination register based on the results of the comparison.
1390     *
1391     * int compare(x, y) {
1392     *     if (x == y) {
1393     *         return 0;
1394     *     } else if (x > y) {
1395     *         return 1;
1396     *     } else if (x < y) {
1397     *         return -1;
1398     *     } else {
1399     *         return -1;
1400     *     }
1401     * }
1402     */
1403    /* op vAA, vBB, vCC */
1404    FETCH(r0, 1)                        @ r0<- CCBB
1405    mov     r9, rINST, lsr #8           @ r9<- AA
1406    and     r2, r0, #255                @ r2<- BB
1407    mov     r3, r0, lsr #8              @ r3<- CC
1408    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1409    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1410    fldd    d0, [r2]                    @ d0<- vBB
1411    fldd    d1, [r3]                    @ d1<- vCC
1412    fcmped  d0, d1                      @ compare (vBB, vCC)
1413    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1414    mvn     r0, #0                      @ r0<- -1 (default)
1415    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1416    fmstat                              @ export status flags
1417    movgt   r0, #1                      @ (greater than) r1<- 1
1418    moveq   r0, #0                      @ (equal) r1<- 0
1419    b       .LOP_CMPL_DOUBLE_finish          @ argh
1420
1421
1422/* ------------------------------ */
1423    .balign 64
1424.L_OP_CMPG_DOUBLE: /* 0x30 */
1425/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1426    /*
1427     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1428     * destination register based on the results of the comparison.
1429     *
1430     * int compare(x, y) {
1431     *     if (x == y) {
1432     *         return 0;
1433     *     } else if (x < y) {
1434     *         return -1;
1435     *     } else if (x > y) {
1436     *         return 1;
1437     *     } else {
1438     *         return 1;
1439     *     }
1440     * }
1441     */
1442    /* op vAA, vBB, vCC */
1443    FETCH(r0, 1)                        @ r0<- CCBB
1444    mov     r9, rINST, lsr #8           @ r9<- AA
1445    and     r2, r0, #255                @ r2<- BB
1446    mov     r3, r0, lsr #8              @ r3<- CC
1447    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1448    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1449    fldd    d0, [r2]                    @ d0<- vBB
1450    fldd    d1, [r3]                    @ d1<- vCC
1451    fcmped  d0, d1                      @ compare (vBB, vCC)
1452    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1453    mov     r0, #1                      @ r0<- 1 (default)
1454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1455    fmstat                              @ export status flags
1456    mvnmi   r0, #0                      @ (less than) r1<- -1
1457    moveq   r0, #0                      @ (equal) r1<- 0
1458    b       .LOP_CMPG_DOUBLE_finish          @ argh
1459
1460
1461/* ------------------------------ */
1462    .balign 64
1463.L_OP_CMP_LONG: /* 0x31 */
1464/* File: armv5te/OP_CMP_LONG.S */
1465    /*
1466     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1467     * register based on the results of the comparison.
1468     *
1469     * We load the full values with LDM, but in practice many values could
1470     * be resolved by only looking at the high word.  This could be made
1471     * faster or slower by splitting the LDM into a pair of LDRs.
1472     *
1473     * If we just wanted to set condition flags, we could do this:
1474     *  subs    ip, r0, r2
1475     *  sbcs    ip, r1, r3
1476     *  subeqs  ip, r0, r2
1477     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1478     * integer value, which we can do with 2 conditional mov/mvn instructions
1479     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1480     * us a constant 5-cycle path plus a branch at the end to the
1481     * instruction epilogue code.  The multi-compare approach below needs
1482     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1483     * in the worst case (the 64-bit values are equal).
1484     */
1485    /* cmp-long vAA, vBB, vCC */
1486    FETCH(r0, 1)                        @ r0<- CCBB
1487    mov     r9, rINST, lsr #8           @ r9<- AA
1488    and     r2, r0, #255                @ r2<- BB
1489    mov     r3, r0, lsr #8              @ r3<- CC
1490    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1491    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1492    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1493    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1494    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1495    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1496    bgt     .LOP_CMP_LONG_greater
1497    subs    r1, r0, r2                  @ r1<- r0 - r2
1498    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1499    bne     .LOP_CMP_LONG_less
1500    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1501
1502/* ------------------------------ */
1503    .balign 64
1504.L_OP_IF_EQ: /* 0x32 */
1505/* File: armv5te/OP_IF_EQ.S */
1506/* File: armv5te/bincmp.S */
1507    /*
1508     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1509     * fragment that specifies the *reverse* comparison to perform, e.g.
1510     * for "if-le" you would use "gt".
1511     *
1512     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1513     */
1514    /* if-cmp vA, vB, +CCCC */
1515    mov     r0, rINST, lsr #8           @ r0<- A+
1516    mov     r1, rINST, lsr #12          @ r1<- B
1517    and     r0, r0, #15
1518    GET_VREG(r3, r1)                    @ r3<- vB
1519    GET_VREG(r2, r0)                    @ r2<- vA
1520    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1521    cmp     r2, r3                      @ compare (vA, vB)
1522    bne  1f                      @ branch to 1 if comparison failed
1523    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1524    movs    r9, r9, asl #1              @ convert to bytes, check sign
1525    bmi     common_backwardBranch       @ yes, do periodic checks
15261:
1527#if defined(WITH_JIT)
1528    GET_JIT_PROF_TABLE(r0)
1529    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1530    b        common_testUpdateProfile
1531#else
1532    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1533    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1534    GOTO_OPCODE(ip)                     @ jump to next instruction
1535#endif
1536
1537
1538
1539/* ------------------------------ */
1540    .balign 64
1541.L_OP_IF_NE: /* 0x33 */
1542/* File: armv5te/OP_IF_NE.S */
1543/* File: armv5te/bincmp.S */
1544    /*
1545     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1546     * fragment that specifies the *reverse* comparison to perform, e.g.
1547     * for "if-le" you would use "gt".
1548     *
1549     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1550     */
1551    /* if-cmp vA, vB, +CCCC */
1552    mov     r0, rINST, lsr #8           @ r0<- A+
1553    mov     r1, rINST, lsr #12          @ r1<- B
1554    and     r0, r0, #15
1555    GET_VREG(r3, r1)                    @ r3<- vB
1556    GET_VREG(r2, r0)                    @ r2<- vA
1557    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1558    cmp     r2, r3                      @ compare (vA, vB)
1559    beq  1f                      @ branch to 1 if comparison failed
1560    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1561    movs    r9, r9, asl #1              @ convert to bytes, check sign
1562    bmi     common_backwardBranch       @ yes, do periodic checks
15631:
1564#if defined(WITH_JIT)
1565    GET_JIT_PROF_TABLE(r0)
1566    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1567    b        common_testUpdateProfile
1568#else
1569    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1571    GOTO_OPCODE(ip)                     @ jump to next instruction
1572#endif
1573
1574
1575
1576/* ------------------------------ */
1577    .balign 64
1578.L_OP_IF_LT: /* 0x34 */
1579/* File: armv5te/OP_IF_LT.S */
1580/* File: armv5te/bincmp.S */
1581    /*
1582     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1583     * fragment that specifies the *reverse* comparison to perform, e.g.
1584     * for "if-le" you would use "gt".
1585     *
1586     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1587     */
1588    /* if-cmp vA, vB, +CCCC */
1589    mov     r0, rINST, lsr #8           @ r0<- A+
1590    mov     r1, rINST, lsr #12          @ r1<- B
1591    and     r0, r0, #15
1592    GET_VREG(r3, r1)                    @ r3<- vB
1593    GET_VREG(r2, r0)                    @ r2<- vA
1594    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1595    cmp     r2, r3                      @ compare (vA, vB)
1596    bge  1f                      @ branch to 1 if comparison failed
1597    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1598    movs    r9, r9, asl #1              @ convert to bytes, check sign
1599    bmi     common_backwardBranch       @ yes, do periodic checks
16001:
1601#if defined(WITH_JIT)
1602    GET_JIT_PROF_TABLE(r0)
1603    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1604    b        common_testUpdateProfile
1605#else
1606    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1608    GOTO_OPCODE(ip)                     @ jump to next instruction
1609#endif
1610
1611
1612
1613/* ------------------------------ */
1614    .balign 64
1615.L_OP_IF_GE: /* 0x35 */
1616/* File: armv5te/OP_IF_GE.S */
1617/* File: armv5te/bincmp.S */
1618    /*
1619     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1620     * fragment that specifies the *reverse* comparison to perform, e.g.
1621     * for "if-le" you would use "gt".
1622     *
1623     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1624     */
1625    /* if-cmp vA, vB, +CCCC */
1626    mov     r0, rINST, lsr #8           @ r0<- A+
1627    mov     r1, rINST, lsr #12          @ r1<- B
1628    and     r0, r0, #15
1629    GET_VREG(r3, r1)                    @ r3<- vB
1630    GET_VREG(r2, r0)                    @ r2<- vA
1631    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1632    cmp     r2, r3                      @ compare (vA, vB)
1633    blt  1f                      @ branch to 1 if comparison failed
1634    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1635    movs    r9, r9, asl #1              @ convert to bytes, check sign
1636    bmi     common_backwardBranch       @ yes, do periodic checks
16371:
1638#if defined(WITH_JIT)
1639    GET_JIT_PROF_TABLE(r0)
1640    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1641    b        common_testUpdateProfile
1642#else
1643    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1645    GOTO_OPCODE(ip)                     @ jump to next instruction
1646#endif
1647
1648
1649
1650/* ------------------------------ */
1651    .balign 64
1652.L_OP_IF_GT: /* 0x36 */
1653/* File: armv5te/OP_IF_GT.S */
1654/* File: armv5te/bincmp.S */
1655    /*
1656     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1657     * fragment that specifies the *reverse* comparison to perform, e.g.
1658     * for "if-le" you would use "gt".
1659     *
1660     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1661     */
1662    /* if-cmp vA, vB, +CCCC */
1663    mov     r0, rINST, lsr #8           @ r0<- A+
1664    mov     r1, rINST, lsr #12          @ r1<- B
1665    and     r0, r0, #15
1666    GET_VREG(r3, r1)                    @ r3<- vB
1667    GET_VREG(r2, r0)                    @ r2<- vA
1668    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1669    cmp     r2, r3                      @ compare (vA, vB)
1670    ble  1f                      @ branch to 1 if comparison failed
1671    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1672    movs    r9, r9, asl #1              @ convert to bytes, check sign
1673    bmi     common_backwardBranch       @ yes, do periodic checks
16741:
1675#if defined(WITH_JIT)
1676    GET_JIT_PROF_TABLE(r0)
1677    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1678    b        common_testUpdateProfile
1679#else
1680    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1681    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1682    GOTO_OPCODE(ip)                     @ jump to next instruction
1683#endif
1684
1685
1686
1687/* ------------------------------ */
1688    .balign 64
1689.L_OP_IF_LE: /* 0x37 */
1690/* File: armv5te/OP_IF_LE.S */
1691/* File: armv5te/bincmp.S */
1692    /*
1693     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1694     * fragment that specifies the *reverse* comparison to perform, e.g.
1695     * for "if-le" you would use "gt".
1696     *
1697     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1698     */
1699    /* if-cmp vA, vB, +CCCC */
1700    mov     r0, rINST, lsr #8           @ r0<- A+
1701    mov     r1, rINST, lsr #12          @ r1<- B
1702    and     r0, r0, #15
1703    GET_VREG(r3, r1)                    @ r3<- vB
1704    GET_VREG(r2, r0)                    @ r2<- vA
1705    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1706    cmp     r2, r3                      @ compare (vA, vB)
1707    bgt  1f                      @ branch to 1 if comparison failed
1708    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1709    movs    r9, r9, asl #1              @ convert to bytes, check sign
1710    bmi     common_backwardBranch       @ yes, do periodic checks
17111:
1712#if defined(WITH_JIT)
1713    GET_JIT_PROF_TABLE(r0)
1714    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1715    b        common_testUpdateProfile
1716#else
1717    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1719    GOTO_OPCODE(ip)                     @ jump to next instruction
1720#endif
1721
1722
1723
1724/* ------------------------------ */
1725    .balign 64
1726.L_OP_IF_EQZ: /* 0x38 */
1727/* File: armv5te/OP_IF_EQZ.S */
1728/* File: armv5te/zcmp.S */
1729    /*
1730     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1731     * fragment that specifies the *reverse* comparison to perform, e.g.
1732     * for "if-le" you would use "gt".
1733     *
1734     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1735     */
1736    /* if-cmp vAA, +BBBB */
1737    mov     r0, rINST, lsr #8           @ r0<- AA
1738    GET_VREG(r2, r0)                    @ r2<- vAA
1739    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1740    cmp     r2, #0                      @ compare (vA, 0)
1741    bne  1f                      @ branch to 1 if comparison failed
1742    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1743    movs    r9, r9, asl #1              @ convert to bytes, check sign
1744    bmi     common_backwardBranch       @ backward branch, do periodic checks
17451:
1746#if defined(WITH_JIT)
1747    GET_JIT_PROF_TABLE(r0)
1748    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1749    cmp     r0,#0
1750    bne     common_updateProfile
1751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1752    GOTO_OPCODE(ip)                     @ jump to next instruction
1753#else
1754    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1755    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1756    GOTO_OPCODE(ip)                     @ jump to next instruction
1757#endif
1758
1759
1760
1761/* ------------------------------ */
1762    .balign 64
1763.L_OP_IF_NEZ: /* 0x39 */
1764/* File: armv5te/OP_IF_NEZ.S */
1765/* File: armv5te/zcmp.S */
1766    /*
1767     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1768     * fragment that specifies the *reverse* comparison to perform, e.g.
1769     * for "if-le" you would use "gt".
1770     *
1771     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1772     */
1773    /* if-cmp vAA, +BBBB */
1774    mov     r0, rINST, lsr #8           @ r0<- AA
1775    GET_VREG(r2, r0)                    @ r2<- vAA
1776    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1777    cmp     r2, #0                      @ compare (vA, 0)
1778    beq  1f                      @ branch to 1 if comparison failed
1779    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1780    movs    r9, r9, asl #1              @ convert to bytes, check sign
1781    bmi     common_backwardBranch       @ backward branch, do periodic checks
17821:
1783#if defined(WITH_JIT)
1784    GET_JIT_PROF_TABLE(r0)
1785    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1786    cmp     r0,#0
1787    bne     common_updateProfile
1788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1789    GOTO_OPCODE(ip)                     @ jump to next instruction
1790#else
1791    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1793    GOTO_OPCODE(ip)                     @ jump to next instruction
1794#endif
1795
1796
1797
1798/* ------------------------------ */
1799    .balign 64
1800.L_OP_IF_LTZ: /* 0x3a */
1801/* File: armv5te/OP_IF_LTZ.S */
1802/* File: armv5te/zcmp.S */
1803    /*
1804     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1805     * fragment that specifies the *reverse* comparison to perform, e.g.
1806     * for "if-le" you would use "gt".
1807     *
1808     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1809     */
1810    /* if-cmp vAA, +BBBB */
1811    mov     r0, rINST, lsr #8           @ r0<- AA
1812    GET_VREG(r2, r0)                    @ r2<- vAA
1813    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1814    cmp     r2, #0                      @ compare (vA, 0)
1815    bge  1f                      @ branch to 1 if comparison failed
1816    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1817    movs    r9, r9, asl #1              @ convert to bytes, check sign
1818    bmi     common_backwardBranch       @ backward branch, do periodic checks
18191:
1820#if defined(WITH_JIT)
1821    GET_JIT_PROF_TABLE(r0)
1822    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1823    cmp     r0,#0
1824    bne     common_updateProfile
1825    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1826    GOTO_OPCODE(ip)                     @ jump to next instruction
1827#else
1828    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1830    GOTO_OPCODE(ip)                     @ jump to next instruction
1831#endif
1832
1833
1834
1835/* ------------------------------ */
1836    .balign 64
1837.L_OP_IF_GEZ: /* 0x3b */
1838/* File: armv5te/OP_IF_GEZ.S */
1839/* File: armv5te/zcmp.S */
1840    /*
1841     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1842     * fragment that specifies the *reverse* comparison to perform, e.g.
1843     * for "if-le" you would use "gt".
1844     *
1845     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1846     */
1847    /* if-cmp vAA, +BBBB */
1848    mov     r0, rINST, lsr #8           @ r0<- AA
1849    GET_VREG(r2, r0)                    @ r2<- vAA
1850    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1851    cmp     r2, #0                      @ compare (vA, 0)
1852    blt  1f                      @ branch to 1 if comparison failed
1853    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1854    movs    r9, r9, asl #1              @ convert to bytes, check sign
1855    bmi     common_backwardBranch       @ backward branch, do periodic checks
18561:
1857#if defined(WITH_JIT)
1858    GET_JIT_PROF_TABLE(r0)
1859    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1860    cmp     r0,#0
1861    bne     common_updateProfile
1862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1863    GOTO_OPCODE(ip)                     @ jump to next instruction
1864#else
1865    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1867    GOTO_OPCODE(ip)                     @ jump to next instruction
1868#endif
1869
1870
1871
1872/* ------------------------------ */
1873    .balign 64
1874.L_OP_IF_GTZ: /* 0x3c */
1875/* File: armv5te/OP_IF_GTZ.S */
1876/* File: armv5te/zcmp.S */
1877    /*
1878     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1879     * fragment that specifies the *reverse* comparison to perform, e.g.
1880     * for "if-le" you would use "gt".
1881     *
1882     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1883     */
1884    /* if-cmp vAA, +BBBB */
1885    mov     r0, rINST, lsr #8           @ r0<- AA
1886    GET_VREG(r2, r0)                    @ r2<- vAA
1887    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1888    cmp     r2, #0                      @ compare (vA, 0)
1889    ble  1f                      @ branch to 1 if comparison failed
1890    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1891    movs    r9, r9, asl #1              @ convert to bytes, check sign
1892    bmi     common_backwardBranch       @ backward branch, do periodic checks
18931:
1894#if defined(WITH_JIT)
1895    GET_JIT_PROF_TABLE(r0)
1896    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1897    cmp     r0,#0
1898    bne     common_updateProfile
1899    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1900    GOTO_OPCODE(ip)                     @ jump to next instruction
1901#else
1902    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1904    GOTO_OPCODE(ip)                     @ jump to next instruction
1905#endif
1906
1907
1908
1909/* ------------------------------ */
1910    .balign 64
1911.L_OP_IF_LEZ: /* 0x3d */
1912/* File: armv5te/OP_IF_LEZ.S */
1913/* File: armv5te/zcmp.S */
1914    /*
1915     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1916     * fragment that specifies the *reverse* comparison to perform, e.g.
1917     * for "if-le" you would use "gt".
1918     *
1919     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1920     */
1921    /* if-cmp vAA, +BBBB */
1922    mov     r0, rINST, lsr #8           @ r0<- AA
1923    GET_VREG(r2, r0)                    @ r2<- vAA
1924    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1925    cmp     r2, #0                      @ compare (vA, 0)
1926    bgt  1f                      @ branch to 1 if comparison failed
1927    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1928    movs    r9, r9, asl #1              @ convert to bytes, check sign
1929    bmi     common_backwardBranch       @ backward branch, do periodic checks
19301:
1931#if defined(WITH_JIT)
1932    GET_JIT_PROF_TABLE(r0)
1933    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1934    cmp     r0,#0
1935    bne     common_updateProfile
1936    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1937    GOTO_OPCODE(ip)                     @ jump to next instruction
1938#else
1939    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1941    GOTO_OPCODE(ip)                     @ jump to next instruction
1942#endif
1943
1944
1945
1946/* ------------------------------ */
1947    .balign 64
1948.L_OP_UNUSED_3E: /* 0x3e */
1949/* File: armv5te/OP_UNUSED_3E.S */
1950/* File: armv5te/unused.S */
1951    bl      common_abort
1952
1953
1954
1955/* ------------------------------ */
1956    .balign 64
1957.L_OP_UNUSED_3F: /* 0x3f */
1958/* File: armv5te/OP_UNUSED_3F.S */
1959/* File: armv5te/unused.S */
1960    bl      common_abort
1961
1962
1963
1964/* ------------------------------ */
1965    .balign 64
1966.L_OP_UNUSED_40: /* 0x40 */
1967/* File: armv5te/OP_UNUSED_40.S */
1968/* File: armv5te/unused.S */
1969    bl      common_abort
1970
1971
1972
1973/* ------------------------------ */
1974    .balign 64
1975.L_OP_UNUSED_41: /* 0x41 */
1976/* File: armv5te/OP_UNUSED_41.S */
1977/* File: armv5te/unused.S */
1978    bl      common_abort
1979
1980
1981
1982/* ------------------------------ */
1983    .balign 64
1984.L_OP_UNUSED_42: /* 0x42 */
1985/* File: armv5te/OP_UNUSED_42.S */
1986/* File: armv5te/unused.S */
1987    bl      common_abort
1988
1989
1990
1991/* ------------------------------ */
1992    .balign 64
1993.L_OP_UNUSED_43: /* 0x43 */
1994/* File: armv5te/OP_UNUSED_43.S */
1995/* File: armv5te/unused.S */
1996    bl      common_abort
1997
1998
1999
2000/* ------------------------------ */
2001    .balign 64
2002.L_OP_AGET: /* 0x44 */
2003/* File: armv5te/OP_AGET.S */
2004    /*
2005     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2006     *
2007     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2008     * instructions.  We use a pair of FETCH_Bs instead.
2009     *
2010     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2011     */
2012    /* op vAA, vBB, vCC */
2013    FETCH_B(r2, 1, 0)                   @ r2<- BB
2014    mov     r9, rINST, lsr #8           @ r9<- AA
2015    FETCH_B(r3, 1, 1)                   @ r3<- CC
2016    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2017    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2018    cmp     r0, #0                      @ null array object?
2019    beq     common_errNullObject        @ yes, bail
2020    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2021    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2022    cmp     r1, r3                      @ compare unsigned index, length
2023    bcs     common_errArrayIndex        @ index >= length, bail
2024    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2025    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2026    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2027    SET_VREG(r2, r9)                    @ vAA<- r2
2028    GOTO_OPCODE(ip)                     @ jump to next instruction
2029
2030
2031/* ------------------------------ */
2032    .balign 64
2033.L_OP_AGET_WIDE: /* 0x45 */
2034/* File: armv5te/OP_AGET_WIDE.S */
2035    /*
2036     * Array get, 64 bits.  vAA <- vBB[vCC].
2037     *
2038     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2039     */
2040    /* aget-wide vAA, vBB, vCC */
2041    FETCH(r0, 1)                        @ r0<- CCBB
2042    mov     r9, rINST, lsr #8           @ r9<- AA
2043    and     r2, r0, #255                @ r2<- BB
2044    mov     r3, r0, lsr #8              @ r3<- CC
2045    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2046    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2047    cmp     r0, #0                      @ null array object?
2048    beq     common_errNullObject        @ yes, bail
2049    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2050    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2051    cmp     r1, r3                      @ compare unsigned index, length
2052    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2053    b       common_errArrayIndex        @ index >= length, bail
2054    @ May want to swap the order of these two branches depending on how the
2055    @ branch prediction (if any) handles conditional forward branches vs.
2056    @ unconditional forward branches.
2057
2058/* ------------------------------ */
2059    .balign 64
2060.L_OP_AGET_OBJECT: /* 0x46 */
2061/* File: armv5te/OP_AGET_OBJECT.S */
2062/* File: armv5te/OP_AGET.S */
2063    /*
2064     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2065     *
2066     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2067     * instructions.  We use a pair of FETCH_Bs instead.
2068     *
2069     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2070     */
2071    /* op vAA, vBB, vCC */
2072    FETCH_B(r2, 1, 0)                   @ r2<- BB
2073    mov     r9, rINST, lsr #8           @ r9<- AA
2074    FETCH_B(r3, 1, 1)                   @ r3<- CC
2075    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2076    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2077    cmp     r0, #0                      @ null array object?
2078    beq     common_errNullObject        @ yes, bail
2079    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2080    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2081    cmp     r1, r3                      @ compare unsigned index, length
2082    bcs     common_errArrayIndex        @ index >= length, bail
2083    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2084    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2085    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2086    SET_VREG(r2, r9)                    @ vAA<- r2
2087    GOTO_OPCODE(ip)                     @ jump to next instruction
2088
2089
2090
2091/* ------------------------------ */
2092    .balign 64
2093.L_OP_AGET_BOOLEAN: /* 0x47 */
2094/* File: armv5te/OP_AGET_BOOLEAN.S */
2095/* File: armv5te/OP_AGET.S */
2096    /*
2097     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2098     *
2099     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2100     * instructions.  We use a pair of FETCH_Bs instead.
2101     *
2102     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2103     */
2104    /* op vAA, vBB, vCC */
2105    FETCH_B(r2, 1, 0)                   @ r2<- BB
2106    mov     r9, rINST, lsr #8           @ r9<- AA
2107    FETCH_B(r3, 1, 1)                   @ r3<- CC
2108    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2109    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2110    cmp     r0, #0                      @ null array object?
2111    beq     common_errNullObject        @ yes, bail
2112    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2113    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2114    cmp     r1, r3                      @ compare unsigned index, length
2115    bcs     common_errArrayIndex        @ index >= length, bail
2116    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2117    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2119    SET_VREG(r2, r9)                    @ vAA<- r2
2120    GOTO_OPCODE(ip)                     @ jump to next instruction
2121
2122
2123
2124/* ------------------------------ */
2125    .balign 64
2126.L_OP_AGET_BYTE: /* 0x48 */
2127/* File: armv5te/OP_AGET_BYTE.S */
2128/* File: armv5te/OP_AGET.S */
2129    /*
2130     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2131     *
2132     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2133     * instructions.  We use a pair of FETCH_Bs instead.
2134     *
2135     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2136     */
2137    /* op vAA, vBB, vCC */
2138    FETCH_B(r2, 1, 0)                   @ r2<- BB
2139    mov     r9, rINST, lsr #8           @ r9<- AA
2140    FETCH_B(r3, 1, 1)                   @ r3<- CC
2141    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2142    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2143    cmp     r0, #0                      @ null array object?
2144    beq     common_errNullObject        @ yes, bail
2145    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2146    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2147    cmp     r1, r3                      @ compare unsigned index, length
2148    bcs     common_errArrayIndex        @ index >= length, bail
2149    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2150    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2152    SET_VREG(r2, r9)                    @ vAA<- r2
2153    GOTO_OPCODE(ip)                     @ jump to next instruction
2154
2155
2156
2157/* ------------------------------ */
2158    .balign 64
2159.L_OP_AGET_CHAR: /* 0x49 */
2160/* File: armv5te/OP_AGET_CHAR.S */
2161/* File: armv5te/OP_AGET.S */
2162    /*
2163     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2164     *
2165     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2166     * instructions.  We use a pair of FETCH_Bs instead.
2167     *
2168     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2169     */
2170    /* op vAA, vBB, vCC */
2171    FETCH_B(r2, 1, 0)                   @ r2<- BB
2172    mov     r9, rINST, lsr #8           @ r9<- AA
2173    FETCH_B(r3, 1, 1)                   @ r3<- CC
2174    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2175    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2176    cmp     r0, #0                      @ null array object?
2177    beq     common_errNullObject        @ yes, bail
2178    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2179    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2180    cmp     r1, r3                      @ compare unsigned index, length
2181    bcs     common_errArrayIndex        @ index >= length, bail
2182    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2183    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2185    SET_VREG(r2, r9)                    @ vAA<- r2
2186    GOTO_OPCODE(ip)                     @ jump to next instruction
2187
2188
2189
2190/* ------------------------------ */
2191    .balign 64
2192.L_OP_AGET_SHORT: /* 0x4a */
2193/* File: armv5te/OP_AGET_SHORT.S */
2194/* File: armv5te/OP_AGET.S */
2195    /*
2196     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2197     *
2198     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2199     * instructions.  We use a pair of FETCH_Bs instead.
2200     *
2201     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2202     */
2203    /* op vAA, vBB, vCC */
2204    FETCH_B(r2, 1, 0)                   @ r2<- BB
2205    mov     r9, rINST, lsr #8           @ r9<- AA
2206    FETCH_B(r3, 1, 1)                   @ r3<- CC
2207    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2208    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2209    cmp     r0, #0                      @ null array object?
2210    beq     common_errNullObject        @ yes, bail
2211    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2212    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2213    cmp     r1, r3                      @ compare unsigned index, length
2214    bcs     common_errArrayIndex        @ index >= length, bail
2215    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2216    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2217    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2218    SET_VREG(r2, r9)                    @ vAA<- r2
2219    GOTO_OPCODE(ip)                     @ jump to next instruction
2220
2221
2222
2223/* ------------------------------ */
2224    .balign 64
2225.L_OP_APUT: /* 0x4b */
2226/* File: armv5te/OP_APUT.S */
2227    /*
2228     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2229     *
2230     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2231     * instructions.  We use a pair of FETCH_Bs instead.
2232     *
2233     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2234     */
2235    /* op vAA, vBB, vCC */
2236    FETCH_B(r2, 1, 0)                   @ r2<- BB
2237    mov     r9, rINST, lsr #8           @ r9<- AA
2238    FETCH_B(r3, 1, 1)                   @ r3<- CC
2239    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2240    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2241    cmp     r0, #0                      @ null array object?
2242    beq     common_errNullObject        @ yes, bail
2243    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2244    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2245    cmp     r1, r3                      @ compare unsigned index, length
2246    bcs     common_errArrayIndex        @ index >= length, bail
2247    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2248    GET_VREG(r2, r9)                    @ r2<- vAA
2249    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2250    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2251    GOTO_OPCODE(ip)                     @ jump to next instruction
2252
2253
2254/* ------------------------------ */
2255    .balign 64
2256.L_OP_APUT_WIDE: /* 0x4c */
2257/* File: armv5te/OP_APUT_WIDE.S */
2258    /*
2259     * Array put, 64 bits.  vBB[vCC] <- vAA.
2260     *
2261     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2262     */
2263    /* aput-wide vAA, vBB, vCC */
2264    FETCH(r0, 1)                        @ r0<- CCBB
2265    mov     r9, rINST, lsr #8           @ r9<- AA
2266    and     r2, r0, #255                @ r2<- BB
2267    mov     r3, r0, lsr #8              @ r3<- CC
2268    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2269    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2270    cmp     r0, #0                      @ null array object?
2271    beq     common_errNullObject        @ yes, bail
2272    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2273    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2274    cmp     r1, r3                      @ compare unsigned index, length
2275    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2276    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2277    b       common_errArrayIndex        @ index >= length, bail
2278    @ May want to swap the order of these two branches depending on how the
2279    @ branch prediction (if any) handles conditional forward branches vs.
2280    @ unconditional forward branches.
2281
2282/* ------------------------------ */
2283    .balign 64
2284.L_OP_APUT_OBJECT: /* 0x4d */
2285/* File: armv5te/OP_APUT_OBJECT.S */
2286    /*
2287     * Store an object into an array.  vBB[vCC] <- vAA.
2288     *
2289     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2290     * instructions.  We use a pair of FETCH_Bs instead.
2291     */
2292    /* op vAA, vBB, vCC */
2293    FETCH(r0, 1)                        @ r0<- CCBB
2294    mov     r9, rINST, lsr #8           @ r9<- AA
2295    and     r2, r0, #255                @ r2<- BB
2296    mov     r3, r0, lsr #8              @ r3<- CC
2297    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2298    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2299    cmp     r1, #0                      @ null array object?
2300    GET_VREG(r9, r9)                    @ r9<- vAA
2301    beq     common_errNullObject        @ yes, bail
2302    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2303    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2304    cmp     r0, r3                      @ compare unsigned index, length
2305    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2306    b       common_errArrayIndex        @ index >= length, bail
2307
2308
2309/* ------------------------------ */
2310    .balign 64
2311.L_OP_APUT_BOOLEAN: /* 0x4e */
2312/* File: armv5te/OP_APUT_BOOLEAN.S */
2313/* File: armv5te/OP_APUT.S */
2314    /*
2315     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2316     *
2317     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2318     * instructions.  We use a pair of FETCH_Bs instead.
2319     *
2320     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2321     */
2322    /* op vAA, vBB, vCC */
2323    FETCH_B(r2, 1, 0)                   @ r2<- BB
2324    mov     r9, rINST, lsr #8           @ r9<- AA
2325    FETCH_B(r3, 1, 1)                   @ r3<- CC
2326    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2327    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2328    cmp     r0, #0                      @ null array object?
2329    beq     common_errNullObject        @ yes, bail
2330    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2331    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2332    cmp     r1, r3                      @ compare unsigned index, length
2333    bcs     common_errArrayIndex        @ index >= length, bail
2334    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2335    GET_VREG(r2, r9)                    @ r2<- vAA
2336    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2337    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2338    GOTO_OPCODE(ip)                     @ jump to next instruction
2339
2340
2341
2342/* ------------------------------ */
2343    .balign 64
2344.L_OP_APUT_BYTE: /* 0x4f */
2345/* File: armv5te/OP_APUT_BYTE.S */
2346/* File: armv5te/OP_APUT.S */
2347    /*
2348     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2349     *
2350     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2351     * instructions.  We use a pair of FETCH_Bs instead.
2352     *
2353     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2354     */
2355    /* op vAA, vBB, vCC */
2356    FETCH_B(r2, 1, 0)                   @ r2<- BB
2357    mov     r9, rINST, lsr #8           @ r9<- AA
2358    FETCH_B(r3, 1, 1)                   @ r3<- CC
2359    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2360    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2361    cmp     r0, #0                      @ null array object?
2362    beq     common_errNullObject        @ yes, bail
2363    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2364    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2365    cmp     r1, r3                      @ compare unsigned index, length
2366    bcs     common_errArrayIndex        @ index >= length, bail
2367    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2368    GET_VREG(r2, r9)                    @ r2<- vAA
2369    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2370    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2371    GOTO_OPCODE(ip)                     @ jump to next instruction
2372
2373
2374
2375/* ------------------------------ */
2376    .balign 64
2377.L_OP_APUT_CHAR: /* 0x50 */
2378/* File: armv5te/OP_APUT_CHAR.S */
2379/* File: armv5te/OP_APUT.S */
2380    /*
2381     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2382     *
2383     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2384     * instructions.  We use a pair of FETCH_Bs instead.
2385     *
2386     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2387     */
2388    /* op vAA, vBB, vCC */
2389    FETCH_B(r2, 1, 0)                   @ r2<- BB
2390    mov     r9, rINST, lsr #8           @ r9<- AA
2391    FETCH_B(r3, 1, 1)                   @ r3<- CC
2392    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2393    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2394    cmp     r0, #0                      @ null array object?
2395    beq     common_errNullObject        @ yes, bail
2396    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2397    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2398    cmp     r1, r3                      @ compare unsigned index, length
2399    bcs     common_errArrayIndex        @ index >= length, bail
2400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2401    GET_VREG(r2, r9)                    @ r2<- vAA
2402    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2403    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2404    GOTO_OPCODE(ip)                     @ jump to next instruction
2405
2406
2407
2408/* ------------------------------ */
2409    .balign 64
2410.L_OP_APUT_SHORT: /* 0x51 */
2411/* File: armv5te/OP_APUT_SHORT.S */
2412/* File: armv5te/OP_APUT.S */
2413    /*
2414     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2415     *
2416     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2417     * instructions.  We use a pair of FETCH_Bs instead.
2418     *
2419     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2420     */
2421    /* op vAA, vBB, vCC */
2422    FETCH_B(r2, 1, 0)                   @ r2<- BB
2423    mov     r9, rINST, lsr #8           @ r9<- AA
2424    FETCH_B(r3, 1, 1)                   @ r3<- CC
2425    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2426    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2427    cmp     r0, #0                      @ null array object?
2428    beq     common_errNullObject        @ yes, bail
2429    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2430    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2431    cmp     r1, r3                      @ compare unsigned index, length
2432    bcs     common_errArrayIndex        @ index >= length, bail
2433    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2434    GET_VREG(r2, r9)                    @ r2<- vAA
2435    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2436    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2437    GOTO_OPCODE(ip)                     @ jump to next instruction
2438
2439
2440
2441/* ------------------------------ */
2442    .balign 64
2443.L_OP_IGET: /* 0x52 */
2444/* File: armv5te/OP_IGET.S */
2445    /*
2446     * General 32-bit instance field get.
2447     *
2448     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2449     */
2450    /* op vA, vB, field@CCCC */
2451    mov     r0, rINST, lsr #12          @ r0<- B
2452    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2453    FETCH(r1, 1)                        @ r1<- field ref CCCC
2454    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2455    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2456    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2457    cmp     r0, #0                      @ is resolved entry null?
2458    bne     .LOP_IGET_finish          @ no, already resolved
24598:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2460    EXPORT_PC()                         @ resolve() could throw
2461    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2462    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2463    cmp     r0, #0
2464    bne     .LOP_IGET_finish
2465    b       common_exceptionThrown
2466
2467/* ------------------------------ */
2468    .balign 64
2469.L_OP_IGET_WIDE: /* 0x53 */
2470/* File: armv5te/OP_IGET_WIDE.S */
2471    /*
2472     * Wide 32-bit instance field get.
2473     */
2474    /* iget-wide vA, vB, field@CCCC */
2475    mov     r0, rINST, lsr #12          @ r0<- B
2476    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2477    FETCH(r1, 1)                        @ r1<- field ref CCCC
2478    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2479    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2480    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2481    cmp     r0, #0                      @ is resolved entry null?
2482    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24838:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2484    EXPORT_PC()                         @ resolve() could throw
2485    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2486    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2487    cmp     r0, #0
2488    bne     .LOP_IGET_WIDE_finish
2489    b       common_exceptionThrown
2490
2491/* ------------------------------ */
2492    .balign 64
2493.L_OP_IGET_OBJECT: /* 0x54 */
2494/* File: armv5te/OP_IGET_OBJECT.S */
2495/* File: armv5te/OP_IGET.S */
2496    /*
2497     * General 32-bit instance field get.
2498     *
2499     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2500     */
2501    /* op vA, vB, field@CCCC */
2502    mov     r0, rINST, lsr #12          @ r0<- B
2503    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2504    FETCH(r1, 1)                        @ r1<- field ref CCCC
2505    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2506    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2507    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2508    cmp     r0, #0                      @ is resolved entry null?
2509    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25108:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2511    EXPORT_PC()                         @ resolve() could throw
2512    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2513    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2514    cmp     r0, #0
2515    bne     .LOP_IGET_OBJECT_finish
2516    b       common_exceptionThrown
2517
2518
2519/* ------------------------------ */
2520    .balign 64
2521.L_OP_IGET_BOOLEAN: /* 0x55 */
2522/* File: armv5te/OP_IGET_BOOLEAN.S */
2523@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2524/* File: armv5te/OP_IGET.S */
2525    /*
2526     * General 32-bit instance field get.
2527     *
2528     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2529     */
2530    /* op vA, vB, field@CCCC */
2531    mov     r0, rINST, lsr #12          @ r0<- B
2532    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2533    FETCH(r1, 1)                        @ r1<- field ref CCCC
2534    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2535    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2536    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2537    cmp     r0, #0                      @ is resolved entry null?
2538    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25398:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2540    EXPORT_PC()                         @ resolve() could throw
2541    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2542    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2543    cmp     r0, #0
2544    bne     .LOP_IGET_BOOLEAN_finish
2545    b       common_exceptionThrown
2546
2547
2548/* ------------------------------ */
2549    .balign 64
2550.L_OP_IGET_BYTE: /* 0x56 */
2551/* File: armv5te/OP_IGET_BYTE.S */
2552@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2553/* File: armv5te/OP_IGET.S */
2554    /*
2555     * General 32-bit instance field get.
2556     *
2557     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2558     */
2559    /* op vA, vB, field@CCCC */
2560    mov     r0, rINST, lsr #12          @ r0<- B
2561    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2562    FETCH(r1, 1)                        @ r1<- field ref CCCC
2563    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2564    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2565    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2566    cmp     r0, #0                      @ is resolved entry null?
2567    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25688:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2569    EXPORT_PC()                         @ resolve() could throw
2570    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2571    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2572    cmp     r0, #0
2573    bne     .LOP_IGET_BYTE_finish
2574    b       common_exceptionThrown
2575
2576
2577/* ------------------------------ */
2578    .balign 64
2579.L_OP_IGET_CHAR: /* 0x57 */
2580/* File: armv5te/OP_IGET_CHAR.S */
2581@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2582/* File: armv5te/OP_IGET.S */
2583    /*
2584     * General 32-bit instance field get.
2585     *
2586     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2587     */
2588    /* op vA, vB, field@CCCC */
2589    mov     r0, rINST, lsr #12          @ r0<- B
2590    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2591    FETCH(r1, 1)                        @ r1<- field ref CCCC
2592    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2593    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2594    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2595    cmp     r0, #0                      @ is resolved entry null?
2596    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25978:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2598    EXPORT_PC()                         @ resolve() could throw
2599    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2600    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2601    cmp     r0, #0
2602    bne     .LOP_IGET_CHAR_finish
2603    b       common_exceptionThrown
2604
2605
2606/* ------------------------------ */
2607    .balign 64
2608.L_OP_IGET_SHORT: /* 0x58 */
2609/* File: armv5te/OP_IGET_SHORT.S */
2610@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2611/* File: armv5te/OP_IGET.S */
2612    /*
2613     * General 32-bit instance field get.
2614     *
2615     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2616     */
2617    /* op vA, vB, field@CCCC */
2618    mov     r0, rINST, lsr #12          @ r0<- B
2619    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2620    FETCH(r1, 1)                        @ r1<- field ref CCCC
2621    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2622    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2623    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2624    cmp     r0, #0                      @ is resolved entry null?
2625    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26268:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2627    EXPORT_PC()                         @ resolve() could throw
2628    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2629    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2630    cmp     r0, #0
2631    bne     .LOP_IGET_SHORT_finish
2632    b       common_exceptionThrown
2633
2634
2635/* ------------------------------ */
2636    .balign 64
2637.L_OP_IPUT: /* 0x59 */
2638/* File: armv5te/OP_IPUT.S */
2639    /*
2640     * General 32-bit instance field put.
2641     *
2642     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2643     */
2644    /* op vA, vB, field@CCCC */
2645    mov     r0, rINST, lsr #12          @ r0<- B
2646    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2647    FETCH(r1, 1)                        @ r1<- field ref CCCC
2648    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2649    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2650    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2651    cmp     r0, #0                      @ is resolved entry null?
2652    bne     .LOP_IPUT_finish          @ no, already resolved
26538:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2654    EXPORT_PC()                         @ resolve() could throw
2655    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2656    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2657    cmp     r0, #0                      @ success?
2658    bne     .LOP_IPUT_finish          @ yes, finish up
2659    b       common_exceptionThrown
2660
2661/* ------------------------------ */
2662    .balign 64
2663.L_OP_IPUT_WIDE: /* 0x5a */
2664/* File: armv5te/OP_IPUT_WIDE.S */
2665    /* iput-wide vA, vB, field@CCCC */
2666    mov     r0, rINST, lsr #12          @ r0<- B
2667    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2668    FETCH(r1, 1)                        @ r1<- field ref CCCC
2669    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2670    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2671    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2672    cmp     r0, #0                      @ is resolved entry null?
2673    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26748:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2675    EXPORT_PC()                         @ resolve() could throw
2676    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2677    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2678    cmp     r0, #0                      @ success?
2679    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2680    b       common_exceptionThrown
2681
2682/* ------------------------------ */
2683    .balign 64
2684.L_OP_IPUT_OBJECT: /* 0x5b */
2685/* File: armv5te/OP_IPUT_OBJECT.S */
2686/* File: armv5te/OP_IPUT.S */
2687    /*
2688     * General 32-bit instance field put.
2689     *
2690     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2691     */
2692    /* op vA, vB, field@CCCC */
2693    mov     r0, rINST, lsr #12          @ r0<- B
2694    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2695    FETCH(r1, 1)                        @ r1<- field ref CCCC
2696    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2697    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2698    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2699    cmp     r0, #0                      @ is resolved entry null?
2700    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
27018:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2702    EXPORT_PC()                         @ resolve() could throw
2703    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2704    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2705    cmp     r0, #0                      @ success?
2706    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2707    b       common_exceptionThrown
2708
2709
2710/* ------------------------------ */
2711    .balign 64
2712.L_OP_IPUT_BOOLEAN: /* 0x5c */
2713/* File: armv5te/OP_IPUT_BOOLEAN.S */
2714@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2715/* File: armv5te/OP_IPUT.S */
2716    /*
2717     * General 32-bit instance field put.
2718     *
2719     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2720     */
2721    /* op vA, vB, field@CCCC */
2722    mov     r0, rINST, lsr #12          @ r0<- B
2723    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2724    FETCH(r1, 1)                        @ r1<- field ref CCCC
2725    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2726    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2727    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2728    cmp     r0, #0                      @ is resolved entry null?
2729    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27308:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2731    EXPORT_PC()                         @ resolve() could throw
2732    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2733    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2734    cmp     r0, #0                      @ success?
2735    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2736    b       common_exceptionThrown
2737
2738
2739/* ------------------------------ */
2740    .balign 64
2741.L_OP_IPUT_BYTE: /* 0x5d */
2742/* File: armv5te/OP_IPUT_BYTE.S */
2743@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2744/* File: armv5te/OP_IPUT.S */
2745    /*
2746     * General 32-bit instance field put.
2747     *
2748     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2749     */
2750    /* op vA, vB, field@CCCC */
2751    mov     r0, rINST, lsr #12          @ r0<- B
2752    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2753    FETCH(r1, 1)                        @ r1<- field ref CCCC
2754    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2755    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2756    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2757    cmp     r0, #0                      @ is resolved entry null?
2758    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27598:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2760    EXPORT_PC()                         @ resolve() could throw
2761    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2762    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2763    cmp     r0, #0                      @ success?
2764    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2765    b       common_exceptionThrown
2766
2767
2768/* ------------------------------ */
2769    .balign 64
2770.L_OP_IPUT_CHAR: /* 0x5e */
2771/* File: armv5te/OP_IPUT_CHAR.S */
2772@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2773/* File: armv5te/OP_IPUT.S */
2774    /*
2775     * General 32-bit instance field put.
2776     *
2777     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2778     */
2779    /* op vA, vB, field@CCCC */
2780    mov     r0, rINST, lsr #12          @ r0<- B
2781    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2782    FETCH(r1, 1)                        @ r1<- field ref CCCC
2783    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2784    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2785    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2786    cmp     r0, #0                      @ is resolved entry null?
2787    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27888:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2789    EXPORT_PC()                         @ resolve() could throw
2790    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2791    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2792    cmp     r0, #0                      @ success?
2793    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2794    b       common_exceptionThrown
2795
2796
2797/* ------------------------------ */
2798    .balign 64
2799.L_OP_IPUT_SHORT: /* 0x5f */
2800/* File: armv5te/OP_IPUT_SHORT.S */
2801@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2802/* File: armv5te/OP_IPUT.S */
2803    /*
2804     * General 32-bit instance field put.
2805     *
2806     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2807     */
2808    /* op vA, vB, field@CCCC */
2809    mov     r0, rINST, lsr #12          @ r0<- B
2810    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2811    FETCH(r1, 1)                        @ r1<- field ref CCCC
2812    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2813    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2814    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2815    cmp     r0, #0                      @ is resolved entry null?
2816    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28178:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2818    EXPORT_PC()                         @ resolve() could throw
2819    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2820    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2821    cmp     r0, #0                      @ success?
2822    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2823    b       common_exceptionThrown
2824
2825
2826/* ------------------------------ */
2827    .balign 64
2828.L_OP_SGET: /* 0x60 */
2829/* File: armv5te/OP_SGET.S */
2830    /*
2831     * General 32-bit SGET handler.
2832     *
2833     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2834     */
2835    /* op vAA, field@BBBB */
2836    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2837    FETCH(r1, 1)                        @ r1<- field ref BBBB
2838    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2839    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2840    cmp     r0, #0                      @ is resolved entry null?
2841    beq     .LOP_SGET_resolve         @ yes, do resolve
2842.LOP_SGET_finish: @ field ptr in r0
2843    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2844    mov     r2, rINST, lsr #8           @ r2<- AA
2845    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2846    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2848    GOTO_OPCODE(ip)                     @ jump to next instruction
2849
2850/* ------------------------------ */
2851    .balign 64
2852.L_OP_SGET_WIDE: /* 0x61 */
2853/* File: armv5te/OP_SGET_WIDE.S */
2854    /*
2855     * 64-bit SGET handler.
2856     */
2857    /* sget-wide vAA, field@BBBB */
2858    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2859    FETCH(r1, 1)                        @ r1<- field ref BBBB
2860    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2861    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2862    cmp     r0, #0                      @ is resolved entry null?
2863    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2864.LOP_SGET_WIDE_finish:
2865    mov     r1, rINST, lsr #8           @ r1<- AA
2866    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2867    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2868    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2869    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2871    GOTO_OPCODE(ip)                     @ jump to next instruction
2872
2873/* ------------------------------ */
2874    .balign 64
2875.L_OP_SGET_OBJECT: /* 0x62 */
2876/* File: armv5te/OP_SGET_OBJECT.S */
2877/* File: armv5te/OP_SGET.S */
2878    /*
2879     * General 32-bit SGET handler.
2880     *
2881     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2882     */
2883    /* op vAA, field@BBBB */
2884    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2885    FETCH(r1, 1)                        @ r1<- field ref BBBB
2886    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2887    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2888    cmp     r0, #0                      @ is resolved entry null?
2889    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2890.LOP_SGET_OBJECT_finish: @ field ptr in r0
2891    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2892    mov     r2, rINST, lsr #8           @ r2<- AA
2893    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2894    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2895    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2896    GOTO_OPCODE(ip)                     @ jump to next instruction
2897
2898
2899/* ------------------------------ */
2900    .balign 64
2901.L_OP_SGET_BOOLEAN: /* 0x63 */
2902/* File: armv5te/OP_SGET_BOOLEAN.S */
2903/* File: armv5te/OP_SGET.S */
2904    /*
2905     * General 32-bit SGET handler.
2906     *
2907     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2908     */
2909    /* op vAA, field@BBBB */
2910    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2911    FETCH(r1, 1)                        @ r1<- field ref BBBB
2912    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2913    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2914    cmp     r0, #0                      @ is resolved entry null?
2915    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2916.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2917    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2918    mov     r2, rINST, lsr #8           @ r2<- AA
2919    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2920    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2921    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2922    GOTO_OPCODE(ip)                     @ jump to next instruction
2923
2924
2925/* ------------------------------ */
2926    .balign 64
2927.L_OP_SGET_BYTE: /* 0x64 */
2928/* File: armv5te/OP_SGET_BYTE.S */
2929/* File: armv5te/OP_SGET.S */
2930    /*
2931     * General 32-bit SGET handler.
2932     *
2933     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2934     */
2935    /* op vAA, field@BBBB */
2936    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2937    FETCH(r1, 1)                        @ r1<- field ref BBBB
2938    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2939    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2940    cmp     r0, #0                      @ is resolved entry null?
2941    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2942.LOP_SGET_BYTE_finish: @ field ptr in r0
2943    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2944    mov     r2, rINST, lsr #8           @ r2<- AA
2945    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948    GOTO_OPCODE(ip)                     @ jump to next instruction
2949
2950
2951/* ------------------------------ */
2952    .balign 64
2953.L_OP_SGET_CHAR: /* 0x65 */
2954/* File: armv5te/OP_SGET_CHAR.S */
2955/* File: armv5te/OP_SGET.S */
2956    /*
2957     * General 32-bit SGET handler.
2958     *
2959     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2960     */
2961    /* op vAA, field@BBBB */
2962    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2963    FETCH(r1, 1)                        @ r1<- field ref BBBB
2964    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2965    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2966    cmp     r0, #0                      @ is resolved entry null?
2967    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2968.LOP_SGET_CHAR_finish: @ field ptr in r0
2969    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2970    mov     r2, rINST, lsr #8           @ r2<- AA
2971    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2972    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2973    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2974    GOTO_OPCODE(ip)                     @ jump to next instruction
2975
2976
2977/* ------------------------------ */
2978    .balign 64
2979.L_OP_SGET_SHORT: /* 0x66 */
2980/* File: armv5te/OP_SGET_SHORT.S */
2981/* File: armv5te/OP_SGET.S */
2982    /*
2983     * General 32-bit SGET handler.
2984     *
2985     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2986     */
2987    /* op vAA, field@BBBB */
2988    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2989    FETCH(r1, 1)                        @ r1<- field ref BBBB
2990    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2991    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2992    cmp     r0, #0                      @ is resolved entry null?
2993    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2994.LOP_SGET_SHORT_finish: @ field ptr in r0
2995    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2996    mov     r2, rINST, lsr #8           @ r2<- AA
2997    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2998    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2999    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3000    GOTO_OPCODE(ip)                     @ jump to next instruction
3001
3002
3003/* ------------------------------ */
3004    .balign 64
3005.L_OP_SPUT: /* 0x67 */
3006/* File: armv5te/OP_SPUT.S */
3007    /*
3008     * General 32-bit SPUT handler.
3009     *
3010     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3011     */
3012    /* op vAA, field@BBBB */
3013    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3014    FETCH(r1, 1)                        @ r1<- field ref BBBB
3015    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3016    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3017    cmp     r0, #0                      @ is resolved entry null?
3018    beq     .LOP_SPUT_resolve         @ yes, do resolve
3019.LOP_SPUT_finish:   @ field ptr in r0
3020    mov     r2, rINST, lsr #8           @ r2<- AA
3021    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3022    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3023    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3024    str     r1, [r0, #offStaticField_value] @ field<- vAA
3025    GOTO_OPCODE(ip)                     @ jump to next instruction
3026
3027/* ------------------------------ */
3028    .balign 64
3029.L_OP_SPUT_WIDE: /* 0x68 */
3030/* File: armv5te/OP_SPUT_WIDE.S */
3031    /*
3032     * 64-bit SPUT handler.
3033     */
3034    /* sput-wide vAA, field@BBBB */
3035    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3036    FETCH(r1, 1)                        @ r1<- field ref BBBB
3037    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3038    mov     r9, rINST, lsr #8           @ r9<- AA
3039    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3040    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3041    cmp     r0, #0                      @ is resolved entry null?
3042    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3043.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3044    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3045    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3047    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3048    GOTO_OPCODE(ip)                     @ jump to next instruction
3049
3050/* ------------------------------ */
3051    .balign 64
3052.L_OP_SPUT_OBJECT: /* 0x69 */
3053/* File: armv5te/OP_SPUT_OBJECT.S */
3054/* File: armv5te/OP_SPUT.S */
3055    /*
3056     * General 32-bit SPUT handler.
3057     *
3058     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3059     */
3060    /* op vAA, field@BBBB */
3061    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3062    FETCH(r1, 1)                        @ r1<- field ref BBBB
3063    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3064    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3065    cmp     r0, #0                      @ is resolved entry null?
3066    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3067.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3068    mov     r2, rINST, lsr #8           @ r2<- AA
3069    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3070    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3071    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3072    str     r1, [r0, #offStaticField_value] @ field<- vAA
3073    GOTO_OPCODE(ip)                     @ jump to next instruction
3074
3075
3076/* ------------------------------ */
3077    .balign 64
3078.L_OP_SPUT_BOOLEAN: /* 0x6a */
3079/* File: armv5te/OP_SPUT_BOOLEAN.S */
3080/* File: armv5te/OP_SPUT.S */
3081    /*
3082     * General 32-bit SPUT handler.
3083     *
3084     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3085     */
3086    /* op vAA, field@BBBB */
3087    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3088    FETCH(r1, 1)                        @ r1<- field ref BBBB
3089    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3090    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3091    cmp     r0, #0                      @ is resolved entry null?
3092    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3093.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3094    mov     r2, rINST, lsr #8           @ r2<- AA
3095    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3096    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3098    str     r1, [r0, #offStaticField_value] @ field<- vAA
3099    GOTO_OPCODE(ip)                     @ jump to next instruction
3100
3101
3102/* ------------------------------ */
3103    .balign 64
3104.L_OP_SPUT_BYTE: /* 0x6b */
3105/* File: armv5te/OP_SPUT_BYTE.S */
3106/* File: armv5te/OP_SPUT.S */
3107    /*
3108     * General 32-bit SPUT handler.
3109     *
3110     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3111     */
3112    /* op vAA, field@BBBB */
3113    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3114    FETCH(r1, 1)                        @ r1<- field ref BBBB
3115    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3116    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3117    cmp     r0, #0                      @ is resolved entry null?
3118    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3119.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3120    mov     r2, rINST, lsr #8           @ r2<- AA
3121    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3122    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3123    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3124    str     r1, [r0, #offStaticField_value] @ field<- vAA
3125    GOTO_OPCODE(ip)                     @ jump to next instruction
3126
3127
3128/* ------------------------------ */
3129    .balign 64
3130.L_OP_SPUT_CHAR: /* 0x6c */
3131/* File: armv5te/OP_SPUT_CHAR.S */
3132/* File: armv5te/OP_SPUT.S */
3133    /*
3134     * General 32-bit SPUT handler.
3135     *
3136     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3137     */
3138    /* op vAA, field@BBBB */
3139    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3140    FETCH(r1, 1)                        @ r1<- field ref BBBB
3141    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3142    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3143    cmp     r0, #0                      @ is resolved entry null?
3144    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3145.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3146    mov     r2, rINST, lsr #8           @ r2<- AA
3147    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3148    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3149    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3150    str     r1, [r0, #offStaticField_value] @ field<- vAA
3151    GOTO_OPCODE(ip)                     @ jump to next instruction
3152
3153
3154/* ------------------------------ */
3155    .balign 64
3156.L_OP_SPUT_SHORT: /* 0x6d */
3157/* File: armv5te/OP_SPUT_SHORT.S */
3158/* File: armv5te/OP_SPUT.S */
3159    /*
3160     * General 32-bit SPUT handler.
3161     *
3162     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3163     */
3164    /* op vAA, field@BBBB */
3165    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3166    FETCH(r1, 1)                        @ r1<- field ref BBBB
3167    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3168    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3169    cmp     r0, #0                      @ is resolved entry null?
3170    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3171.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3172    mov     r2, rINST, lsr #8           @ r2<- AA
3173    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3174    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3175    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3176    str     r1, [r0, #offStaticField_value] @ field<- vAA
3177    GOTO_OPCODE(ip)                     @ jump to next instruction
3178
3179
3180/* ------------------------------ */
3181    .balign 64
3182.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3183/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3184    /*
3185     * Handle a virtual method call.
3186     *
3187     * for: invoke-virtual, invoke-virtual/range
3188     */
3189    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3190    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3191    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3192    FETCH(r1, 1)                        @ r1<- BBBB
3193    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3194    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3195    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3196    .if     (!0)
3197    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3198    .endif
3199    cmp     r0, #0                      @ already resolved?
3200    EXPORT_PC()                         @ must export for invoke
3201    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3202    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3203    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3204    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3205    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3206    cmp     r0, #0                      @ got null?
3207    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3208    b       common_exceptionThrown      @ yes, handle exception
3209
3210/* ------------------------------ */
3211    .balign 64
3212.L_OP_INVOKE_SUPER: /* 0x6f */
3213/* File: armv5te/OP_INVOKE_SUPER.S */
3214    /*
3215     * Handle a "super" method call.
3216     *
3217     * for: invoke-super, invoke-super/range
3218     */
3219    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3220    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3221    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3222    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3223    .if     (!0)
3224    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3225    .endif
3226    FETCH(r1, 1)                        @ r1<- BBBB
3227    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3228    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3229    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3230    cmp     r2, #0                      @ null "this"?
3231    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3232    beq     common_errNullObject        @ null "this", throw exception
3233    cmp     r0, #0                      @ already resolved?
3234    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3235    EXPORT_PC()                         @ must export for invoke
3236    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3237    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3238
3239/* ------------------------------ */
3240    .balign 64
3241.L_OP_INVOKE_DIRECT: /* 0x70 */
3242/* File: armv5te/OP_INVOKE_DIRECT.S */
3243    /*
3244     * Handle a direct method call.
3245     *
3246     * (We could defer the "is 'this' pointer null" test to the common
3247     * method invocation code, and use a flag to indicate that static
3248     * calls don't count.  If we do this as part of copying the arguments
3249     * out we could avoiding loading the first arg twice.)
3250     *
3251     * for: invoke-direct, invoke-direct/range
3252     */
3253    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3254    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3255    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3256    FETCH(r1, 1)                        @ r1<- BBBB
3257    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3258    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3259    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3260    .if     (!0)
3261    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3262    .endif
3263    cmp     r0, #0                      @ already resolved?
3264    EXPORT_PC()                         @ must export for invoke
3265    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3266    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3267.LOP_INVOKE_DIRECT_finish:
3268    cmp     r2, #0                      @ null "this" ref?
3269    bne     common_invokeMethodNoRange   @ no, continue on
3270    b       common_errNullObject        @ yes, throw exception
3271
3272/* ------------------------------ */
3273    .balign 64
3274.L_OP_INVOKE_STATIC: /* 0x71 */
3275/* File: armv5te/OP_INVOKE_STATIC.S */
3276    /*
3277     * Handle a static method call.
3278     *
3279     * for: invoke-static, invoke-static/range
3280     */
3281    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3282    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3283    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3284    FETCH(r1, 1)                        @ r1<- BBBB
3285    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3286    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3287    cmp     r0, #0                      @ already resolved?
3288    EXPORT_PC()                         @ must export for invoke
3289    bne     common_invokeMethodNoRange @ yes, continue on
32900:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3291    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3292    mov     r2, #METHOD_STATIC          @ resolver method type
3293    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3294    cmp     r0, #0                      @ got null?
3295    bne     common_invokeMethodNoRange @ no, continue
3296    b       common_exceptionThrown      @ yes, handle exception
3297
3298
3299/* ------------------------------ */
3300    .balign 64
3301.L_OP_INVOKE_INTERFACE: /* 0x72 */
3302/* File: armv5te/OP_INVOKE_INTERFACE.S */
3303    /*
3304     * Handle an interface method call.
3305     *
3306     * for: invoke-interface, invoke-interface/range
3307     */
3308    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3309    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3310    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3311    FETCH(r1, 1)                        @ r1<- BBBB
3312    .if     (!0)
3313    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3314    .endif
3315    EXPORT_PC()                         @ must export for invoke
3316    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3317    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3318    cmp     r0, #0                      @ null obj?
3319    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3320    beq     common_errNullObject        @ yes, fail
3321    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3322    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3323    cmp     r0, #0                      @ failed?
3324    beq     common_exceptionThrown      @ yes, handle exception
3325    b       common_invokeMethodNoRange @ jump to common handler
3326
3327
3328/* ------------------------------ */
3329    .balign 64
3330.L_OP_UNUSED_73: /* 0x73 */
3331/* File: armv5te/OP_UNUSED_73.S */
3332/* File: armv5te/unused.S */
3333    bl      common_abort
3334
3335
3336
3337/* ------------------------------ */
3338    .balign 64
3339.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3340/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3341/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3342    /*
3343     * Handle a virtual method call.
3344     *
3345     * for: invoke-virtual, invoke-virtual/range
3346     */
3347    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3348    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3349    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3350    FETCH(r1, 1)                        @ r1<- BBBB
3351    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3352    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3353    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3354    .if     (!1)
3355    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3356    .endif
3357    cmp     r0, #0                      @ already resolved?
3358    EXPORT_PC()                         @ must export for invoke
3359    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3360    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3361    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3362    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3363    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3364    cmp     r0, #0                      @ got null?
3365    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3366    b       common_exceptionThrown      @ yes, handle exception
3367
3368
3369/* ------------------------------ */
3370    .balign 64
3371.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3372/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3373/* File: armv5te/OP_INVOKE_SUPER.S */
3374    /*
3375     * Handle a "super" method call.
3376     *
3377     * for: invoke-super, invoke-super/range
3378     */
3379    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3380    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3381    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3382    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3383    .if     (!1)
3384    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3385    .endif
3386    FETCH(r1, 1)                        @ r1<- BBBB
3387    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3388    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3389    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3390    cmp     r2, #0                      @ null "this"?
3391    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3392    beq     common_errNullObject        @ null "this", throw exception
3393    cmp     r0, #0                      @ already resolved?
3394    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3395    EXPORT_PC()                         @ must export for invoke
3396    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3397    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3398
3399
3400/* ------------------------------ */
3401    .balign 64
3402.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3403/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3404/* File: armv5te/OP_INVOKE_DIRECT.S */
3405    /*
3406     * Handle a direct method call.
3407     *
3408     * (We could defer the "is 'this' pointer null" test to the common
3409     * method invocation code, and use a flag to indicate that static
3410     * calls don't count.  If we do this as part of copying the arguments
3411     * out we could avoiding loading the first arg twice.)
3412     *
3413     * for: invoke-direct, invoke-direct/range
3414     */
3415    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3416    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3417    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3418    FETCH(r1, 1)                        @ r1<- BBBB
3419    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3420    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3421    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3422    .if     (!1)
3423    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3424    .endif
3425    cmp     r0, #0                      @ already resolved?
3426    EXPORT_PC()                         @ must export for invoke
3427    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3428    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3429.LOP_INVOKE_DIRECT_RANGE_finish:
3430    cmp     r2, #0                      @ null "this" ref?
3431    bne     common_invokeMethodRange   @ no, continue on
3432    b       common_errNullObject        @ yes, throw exception
3433
3434
3435/* ------------------------------ */
3436    .balign 64
3437.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3438/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3439/* File: armv5te/OP_INVOKE_STATIC.S */
3440    /*
3441     * Handle a static method call.
3442     *
3443     * for: invoke-static, invoke-static/range
3444     */
3445    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3446    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3447    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3448    FETCH(r1, 1)                        @ r1<- BBBB
3449    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3450    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3451    cmp     r0, #0                      @ already resolved?
3452    EXPORT_PC()                         @ must export for invoke
3453    bne     common_invokeMethodRange @ yes, continue on
34540:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3455    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3456    mov     r2, #METHOD_STATIC          @ resolver method type
3457    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3458    cmp     r0, #0                      @ got null?
3459    bne     common_invokeMethodRange @ no, continue
3460    b       common_exceptionThrown      @ yes, handle exception
3461
3462
3463
3464/* ------------------------------ */
3465    .balign 64
3466.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3467/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3468/* File: armv5te/OP_INVOKE_INTERFACE.S */
3469    /*
3470     * Handle an interface method call.
3471     *
3472     * for: invoke-interface, invoke-interface/range
3473     */
3474    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3475    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3476    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3477    FETCH(r1, 1)                        @ r1<- BBBB
3478    .if     (!1)
3479    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3480    .endif
3481    EXPORT_PC()                         @ must export for invoke
3482    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3483    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3484    cmp     r0, #0                      @ null obj?
3485    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3486    beq     common_errNullObject        @ yes, fail
3487    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3488    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3489    cmp     r0, #0                      @ failed?
3490    beq     common_exceptionThrown      @ yes, handle exception
3491    b       common_invokeMethodRange @ jump to common handler
3492
3493
3494
3495/* ------------------------------ */
3496    .balign 64
3497.L_OP_UNUSED_79: /* 0x79 */
3498/* File: armv5te/OP_UNUSED_79.S */
3499/* File: armv5te/unused.S */
3500    bl      common_abort
3501
3502
3503
3504/* ------------------------------ */
3505    .balign 64
3506.L_OP_UNUSED_7A: /* 0x7a */
3507/* File: armv5te/OP_UNUSED_7A.S */
3508/* File: armv5te/unused.S */
3509    bl      common_abort
3510
3511
3512
3513/* ------------------------------ */
3514    .balign 64
3515.L_OP_NEG_INT: /* 0x7b */
3516/* File: armv5te/OP_NEG_INT.S */
3517/* File: armv5te/unop.S */
3518    /*
3519     * Generic 32-bit unary operation.  Provide an "instr" line that
3520     * specifies an instruction that performs "result = op r0".
3521     * This could be an ARM instruction or a function call.
3522     *
3523     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3524     *      int-to-byte, int-to-char, int-to-short
3525     */
3526    /* unop vA, vB */
3527    mov     r3, rINST, lsr #12          @ r3<- B
3528    mov     r9, rINST, lsr #8           @ r9<- A+
3529    GET_VREG(r0, r3)                    @ r0<- vB
3530    and     r9, r9, #15
3531                               @ optional op; may set condition codes
3532    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3533    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3534    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3535    SET_VREG(r0, r9)                    @ vAA<- r0
3536    GOTO_OPCODE(ip)                     @ jump to next instruction
3537    /* 9-10 instructions */
3538
3539
3540/* ------------------------------ */
3541    .balign 64
3542.L_OP_NOT_INT: /* 0x7c */
3543/* File: armv5te/OP_NOT_INT.S */
3544/* File: armv5te/unop.S */
3545    /*
3546     * Generic 32-bit unary operation.  Provide an "instr" line that
3547     * specifies an instruction that performs "result = op r0".
3548     * This could be an ARM instruction or a function call.
3549     *
3550     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3551     *      int-to-byte, int-to-char, int-to-short
3552     */
3553    /* unop vA, vB */
3554    mov     r3, rINST, lsr #12          @ r3<- B
3555    mov     r9, rINST, lsr #8           @ r9<- A+
3556    GET_VREG(r0, r3)                    @ r0<- vB
3557    and     r9, r9, #15
3558                               @ optional op; may set condition codes
3559    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3560    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3561    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3562    SET_VREG(r0, r9)                    @ vAA<- r0
3563    GOTO_OPCODE(ip)                     @ jump to next instruction
3564    /* 9-10 instructions */
3565
3566
3567/* ------------------------------ */
3568    .balign 64
3569.L_OP_NEG_LONG: /* 0x7d */
3570/* File: armv5te/OP_NEG_LONG.S */
3571/* File: armv5te/unopWide.S */
3572    /*
3573     * Generic 64-bit unary operation.  Provide an "instr" line that
3574     * specifies an instruction that performs "result = op r0/r1".
3575     * This could be an ARM instruction or a function call.
3576     *
3577     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3578     */
3579    /* unop vA, vB */
3580    mov     r9, rINST, lsr #8           @ r9<- A+
3581    mov     r3, rINST, lsr #12          @ r3<- B
3582    and     r9, r9, #15
3583    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3584    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3585    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3586    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3587    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3588    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3589    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3590    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3591    GOTO_OPCODE(ip)                     @ jump to next instruction
3592    /* 12-13 instructions */
3593
3594
3595
3596/* ------------------------------ */
3597    .balign 64
3598.L_OP_NOT_LONG: /* 0x7e */
3599/* File: armv5te/OP_NOT_LONG.S */
3600/* File: armv5te/unopWide.S */
3601    /*
3602     * Generic 64-bit unary operation.  Provide an "instr" line that
3603     * specifies an instruction that performs "result = op r0/r1".
3604     * This could be an ARM instruction or a function call.
3605     *
3606     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3607     */
3608    /* unop vA, vB */
3609    mov     r9, rINST, lsr #8           @ r9<- A+
3610    mov     r3, rINST, lsr #12          @ r3<- B
3611    and     r9, r9, #15
3612    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3613    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3614    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3615    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3616    mvn     r0, r0                           @ optional op; may set condition codes
3617    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3618    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3619    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3620    GOTO_OPCODE(ip)                     @ jump to next instruction
3621    /* 12-13 instructions */
3622
3623
3624
3625/* ------------------------------ */
3626    .balign 64
3627.L_OP_NEG_FLOAT: /* 0x7f */
3628/* File: armv5te/OP_NEG_FLOAT.S */
3629/* File: armv5te/unop.S */
3630    /*
3631     * Generic 32-bit unary operation.  Provide an "instr" line that
3632     * specifies an instruction that performs "result = op r0".
3633     * This could be an ARM instruction or a function call.
3634     *
3635     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3636     *      int-to-byte, int-to-char, int-to-short
3637     */
3638    /* unop vA, vB */
3639    mov     r3, rINST, lsr #12          @ r3<- B
3640    mov     r9, rINST, lsr #8           @ r9<- A+
3641    GET_VREG(r0, r3)                    @ r0<- vB
3642    and     r9, r9, #15
3643                               @ optional op; may set condition codes
3644    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3645    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3646    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3647    SET_VREG(r0, r9)                    @ vAA<- r0
3648    GOTO_OPCODE(ip)                     @ jump to next instruction
3649    /* 9-10 instructions */
3650
3651
3652/* ------------------------------ */
3653    .balign 64
3654.L_OP_NEG_DOUBLE: /* 0x80 */
3655/* File: armv5te/OP_NEG_DOUBLE.S */
3656/* File: armv5te/unopWide.S */
3657    /*
3658     * Generic 64-bit unary operation.  Provide an "instr" line that
3659     * specifies an instruction that performs "result = op r0/r1".
3660     * This could be an ARM instruction or a function call.
3661     *
3662     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3663     */
3664    /* unop vA, vB */
3665    mov     r9, rINST, lsr #8           @ r9<- A+
3666    mov     r3, rINST, lsr #12          @ r3<- B
3667    and     r9, r9, #15
3668    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3669    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3670    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3671    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3672                               @ optional op; may set condition codes
3673    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3674    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3675    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3676    GOTO_OPCODE(ip)                     @ jump to next instruction
3677    /* 12-13 instructions */
3678
3679
3680
3681/* ------------------------------ */
3682    .balign 64
3683.L_OP_INT_TO_LONG: /* 0x81 */
3684/* File: armv5te/OP_INT_TO_LONG.S */
3685/* File: armv5te/unopWider.S */
3686    /*
3687     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3688     * that specifies an instruction that performs "result = op r0", where
3689     * "result" is a 64-bit quantity in r0/r1.
3690     *
3691     * For: int-to-long, int-to-double, float-to-long, float-to-double
3692     */
3693    /* unop vA, vB */
3694    mov     r9, rINST, lsr #8           @ r9<- A+
3695    mov     r3, rINST, lsr #12          @ r3<- B
3696    and     r9, r9, #15
3697    GET_VREG(r0, r3)                    @ r0<- vB
3698    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3699                               @ optional op; may set condition codes
3700    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3701    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3702    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3703    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3704    GOTO_OPCODE(ip)                     @ jump to next instruction
3705    /* 10-11 instructions */
3706
3707
3708/* ------------------------------ */
3709    .balign 64
3710.L_OP_INT_TO_FLOAT: /* 0x82 */
3711/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3712/* File: arm-vfp/funop.S */
3713    /*
3714     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3715     * line that specifies an instruction that performs "s1 = op s0".
3716     *
3717     * for: int-to-float, float-to-int
3718     */
3719    /* unop vA, vB */
3720    mov     r3, rINST, lsr #12          @ r3<- B
3721    mov     r9, rINST, lsr #8           @ r9<- A+
3722    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3723    flds    s0, [r3]                    @ s0<- vB
3724    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3725    and     r9, r9, #15                 @ r9<- A
3726    fsitos  s1, s0                              @ s1<- op
3727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3728    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3729    fsts    s1, [r9]                    @ vA<- s1
3730    GOTO_OPCODE(ip)                     @ jump to next instruction
3731
3732
3733/* ------------------------------ */
3734    .balign 64
3735.L_OP_INT_TO_DOUBLE: /* 0x83 */
3736/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3737/* File: arm-vfp/funopWider.S */
3738    /*
3739     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3740     * "instr" line that specifies an instruction that performs "d0 = op s0".
3741     *
3742     * For: int-to-double, float-to-double
3743     */
3744    /* unop vA, vB */
3745    mov     r3, rINST, lsr #12          @ r3<- B
3746    mov     r9, rINST, lsr #8           @ r9<- A+
3747    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3748    flds    s0, [r3]                    @ s0<- vB
3749    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3750    and     r9, r9, #15                 @ r9<- A
3751    fsitod  d0, s0                              @ d0<- op
3752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3753    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3754    fstd    d0, [r9]                    @ vA<- d0
3755    GOTO_OPCODE(ip)                     @ jump to next instruction
3756
3757
3758/* ------------------------------ */
3759    .balign 64
3760.L_OP_LONG_TO_INT: /* 0x84 */
3761/* File: armv5te/OP_LONG_TO_INT.S */
3762/* we ignore the high word, making this equivalent to a 32-bit reg move */
3763/* File: armv5te/OP_MOVE.S */
3764    /* for move, move-object, long-to-int */
3765    /* op vA, vB */
3766    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3767    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3768    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3769    GET_VREG(r2, r1)                    @ r2<- fp[B]
3770    and     r0, r0, #15
3771    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3772    SET_VREG(r2, r0)                    @ fp[A]<- r2
3773    GOTO_OPCODE(ip)                     @ execute next instruction
3774
3775
3776
3777/* ------------------------------ */
3778    .balign 64
3779.L_OP_LONG_TO_FLOAT: /* 0x85 */
3780/* File: armv5te/OP_LONG_TO_FLOAT.S */
3781/* File: armv5te/unopNarrower.S */
3782    /*
3783     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3784     * that specifies an instruction that performs "result = op r0/r1", where
3785     * "result" is a 32-bit quantity in r0.
3786     *
3787     * For: long-to-float, double-to-int, double-to-float
3788     *
3789     * (This would work for long-to-int, but that instruction is actually
3790     * an exact match for OP_MOVE.)
3791     */
3792    /* unop vA, vB */
3793    mov     r3, rINST, lsr #12          @ r3<- B
3794    mov     r9, rINST, lsr #8           @ r9<- A+
3795    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3796    and     r9, r9, #15
3797    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3798    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3799                               @ optional op; may set condition codes
3800    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3802    SET_VREG(r0, r9)                    @ vA<- r0
3803    GOTO_OPCODE(ip)                     @ jump to next instruction
3804    /* 10-11 instructions */
3805
3806
3807/* ------------------------------ */
3808    .balign 64
3809.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3810/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3811/* File: armv5te/unopWide.S */
3812    /*
3813     * Generic 64-bit unary operation.  Provide an "instr" line that
3814     * specifies an instruction that performs "result = op r0/r1".
3815     * This could be an ARM instruction or a function call.
3816     *
3817     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3818     */
3819    /* unop vA, vB */
3820    mov     r9, rINST, lsr #8           @ r9<- A+
3821    mov     r3, rINST, lsr #12          @ r3<- B
3822    and     r9, r9, #15
3823    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3824    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3825    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3826    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3827                               @ optional op; may set condition codes
3828    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3830    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3831    GOTO_OPCODE(ip)                     @ jump to next instruction
3832    /* 12-13 instructions */
3833
3834
3835
3836/* ------------------------------ */
3837    .balign 64
3838.L_OP_FLOAT_TO_INT: /* 0x87 */
3839/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3840/* File: arm-vfp/funop.S */
3841    /*
3842     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3843     * line that specifies an instruction that performs "s1 = op s0".
3844     *
3845     * for: int-to-float, float-to-int
3846     */
3847    /* unop vA, vB */
3848    mov     r3, rINST, lsr #12          @ r3<- B
3849    mov     r9, rINST, lsr #8           @ r9<- A+
3850    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3851    flds    s0, [r3]                    @ s0<- vB
3852    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3853    and     r9, r9, #15                 @ r9<- A
3854    ftosizs s1, s0                              @ s1<- op
3855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3856    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3857    fsts    s1, [r9]                    @ vA<- s1
3858    GOTO_OPCODE(ip)                     @ jump to next instruction
3859
3860
3861/* ------------------------------ */
3862    .balign 64
3863.L_OP_FLOAT_TO_LONG: /* 0x88 */
3864/* File: armv5te/OP_FLOAT_TO_LONG.S */
3865@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3866/* File: armv5te/unopWider.S */
3867    /*
3868     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3869     * that specifies an instruction that performs "result = op r0", where
3870     * "result" is a 64-bit quantity in r0/r1.
3871     *
3872     * For: int-to-long, int-to-double, float-to-long, float-to-double
3873     */
3874    /* unop vA, vB */
3875    mov     r9, rINST, lsr #8           @ r9<- A+
3876    mov     r3, rINST, lsr #12          @ r3<- B
3877    and     r9, r9, #15
3878    GET_VREG(r0, r3)                    @ r0<- vB
3879    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3880                               @ optional op; may set condition codes
3881    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3882    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3883    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3884    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3885    GOTO_OPCODE(ip)                     @ jump to next instruction
3886    /* 10-11 instructions */
3887
3888
3889
3890/* ------------------------------ */
3891    .balign 64
3892.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3893/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3894/* File: arm-vfp/funopWider.S */
3895    /*
3896     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3897     * "instr" line that specifies an instruction that performs "d0 = op s0".
3898     *
3899     * For: int-to-double, float-to-double
3900     */
3901    /* unop vA, vB */
3902    mov     r3, rINST, lsr #12          @ r3<- B
3903    mov     r9, rINST, lsr #8           @ r9<- A+
3904    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3905    flds    s0, [r3]                    @ s0<- vB
3906    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3907    and     r9, r9, #15                 @ r9<- A
3908    fcvtds  d0, s0                              @ d0<- op
3909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3910    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3911    fstd    d0, [r9]                    @ vA<- d0
3912    GOTO_OPCODE(ip)                     @ jump to next instruction
3913
3914
3915/* ------------------------------ */
3916    .balign 64
3917.L_OP_DOUBLE_TO_INT: /* 0x8a */
3918/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3919/* File: arm-vfp/funopNarrower.S */
3920    /*
3921     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3922     * "instr" line that specifies an instruction that performs "s0 = op d0".
3923     *
3924     * For: double-to-int, double-to-float
3925     */
3926    /* unop vA, vB */
3927    mov     r3, rINST, lsr #12          @ r3<- B
3928    mov     r9, rINST, lsr #8           @ r9<- A+
3929    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3930    fldd    d0, [r3]                    @ d0<- vB
3931    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3932    and     r9, r9, #15                 @ r9<- A
3933    ftosizd  s0, d0                              @ s0<- op
3934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3935    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3936    fsts    s0, [r9]                    @ vA<- s0
3937    GOTO_OPCODE(ip)                     @ jump to next instruction
3938
3939
3940/* ------------------------------ */
3941    .balign 64
3942.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3943/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3944@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3945/* File: armv5te/unopWide.S */
3946    /*
3947     * Generic 64-bit unary operation.  Provide an "instr" line that
3948     * specifies an instruction that performs "result = op r0/r1".
3949     * This could be an ARM instruction or a function call.
3950     *
3951     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3952     */
3953    /* unop vA, vB */
3954    mov     r9, rINST, lsr #8           @ r9<- A+
3955    mov     r3, rINST, lsr #12          @ r3<- B
3956    and     r9, r9, #15
3957    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3958    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3959    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3960    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3961                               @ optional op; may set condition codes
3962    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3963    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3964    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3965    GOTO_OPCODE(ip)                     @ jump to next instruction
3966    /* 12-13 instructions */
3967
3968
3969
3970
3971/* ------------------------------ */
3972    .balign 64
3973.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3974/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3975/* File: arm-vfp/funopNarrower.S */
3976    /*
3977     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3978     * "instr" line that specifies an instruction that performs "s0 = op d0".
3979     *
3980     * For: double-to-int, double-to-float
3981     */
3982    /* unop vA, vB */
3983    mov     r3, rINST, lsr #12          @ r3<- B
3984    mov     r9, rINST, lsr #8           @ r9<- A+
3985    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3986    fldd    d0, [r3]                    @ d0<- vB
3987    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3988    and     r9, r9, #15                 @ r9<- A
3989    fcvtsd  s0, d0                              @ s0<- op
3990    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3991    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3992    fsts    s0, [r9]                    @ vA<- s0
3993    GOTO_OPCODE(ip)                     @ jump to next instruction
3994
3995
3996/* ------------------------------ */
3997    .balign 64
3998.L_OP_INT_TO_BYTE: /* 0x8d */
3999/* File: armv5te/OP_INT_TO_BYTE.S */
4000/* File: armv5te/unop.S */
4001    /*
4002     * Generic 32-bit unary operation.  Provide an "instr" line that
4003     * specifies an instruction that performs "result = op r0".
4004     * This could be an ARM instruction or a function call.
4005     *
4006     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4007     *      int-to-byte, int-to-char, int-to-short
4008     */
4009    /* unop vA, vB */
4010    mov     r3, rINST, lsr #12          @ r3<- B
4011    mov     r9, rINST, lsr #8           @ r9<- A+
4012    GET_VREG(r0, r3)                    @ r0<- vB
4013    and     r9, r9, #15
4014    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4015    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4016    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4017    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4018    SET_VREG(r0, r9)                    @ vAA<- r0
4019    GOTO_OPCODE(ip)                     @ jump to next instruction
4020    /* 9-10 instructions */
4021
4022
4023/* ------------------------------ */
4024    .balign 64
4025.L_OP_INT_TO_CHAR: /* 0x8e */
4026/* File: armv5te/OP_INT_TO_CHAR.S */
4027/* File: armv5te/unop.S */
4028    /*
4029     * Generic 32-bit unary operation.  Provide an "instr" line that
4030     * specifies an instruction that performs "result = op r0".
4031     * This could be an ARM instruction or a function call.
4032     *
4033     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4034     *      int-to-byte, int-to-char, int-to-short
4035     */
4036    /* unop vA, vB */
4037    mov     r3, rINST, lsr #12          @ r3<- B
4038    mov     r9, rINST, lsr #8           @ r9<- A+
4039    GET_VREG(r0, r3)                    @ r0<- vB
4040    and     r9, r9, #15
4041    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4042    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4043    mov     r0, r0, lsr #16                              @ 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    /* 9-10 instructions */
4048
4049
4050/* ------------------------------ */
4051    .balign 64
4052.L_OP_INT_TO_SHORT: /* 0x8f */
4053/* File: armv5te/OP_INT_TO_SHORT.S */
4054/* File: armv5te/unop.S */
4055    /*
4056     * Generic 32-bit unary operation.  Provide an "instr" line that
4057     * specifies an instruction that performs "result = op r0".
4058     * This could be an ARM instruction or a function call.
4059     *
4060     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4061     *      int-to-byte, int-to-char, int-to-short
4062     */
4063    /* unop vA, vB */
4064    mov     r3, rINST, lsr #12          @ r3<- B
4065    mov     r9, rINST, lsr #8           @ r9<- A+
4066    GET_VREG(r0, r3)                    @ r0<- vB
4067    and     r9, r9, #15
4068    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4069    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4070    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4071    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4072    SET_VREG(r0, r9)                    @ vAA<- r0
4073    GOTO_OPCODE(ip)                     @ jump to next instruction
4074    /* 9-10 instructions */
4075
4076
4077/* ------------------------------ */
4078    .balign 64
4079.L_OP_ADD_INT: /* 0x90 */
4080/* File: armv5te/OP_ADD_INT.S */
4081/* File: armv5te/binop.S */
4082    /*
4083     * Generic 32-bit binary operation.  Provide an "instr" line that
4084     * specifies an instruction that performs "result = r0 op r1".
4085     * This could be an ARM instruction or a function call.  (If the result
4086     * comes back in a register other than r0, you can override "result".)
4087     *
4088     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4089     * vCC (r1).  Useful for integer division and modulus.  Note that we
4090     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4091     * handles it correctly.
4092     *
4093     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4094     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4095     *      mul-float, div-float, rem-float
4096     */
4097    /* binop vAA, vBB, vCC */
4098    FETCH(r0, 1)                        @ r0<- CCBB
4099    mov     r9, rINST, lsr #8           @ r9<- AA
4100    mov     r3, r0, lsr #8              @ r3<- CC
4101    and     r2, r0, #255                @ r2<- BB
4102    GET_VREG(r1, r3)                    @ r1<- vCC
4103    GET_VREG(r0, r2)                    @ r0<- vBB
4104    .if 0
4105    cmp     r1, #0                      @ is second operand zero?
4106    beq     common_errDivideByZero
4107    .endif
4108
4109    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4110                               @ optional op; may set condition codes
4111    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4113    SET_VREG(r0, r9)               @ vAA<- r0
4114    GOTO_OPCODE(ip)                     @ jump to next instruction
4115    /* 11-14 instructions */
4116
4117
4118
4119/* ------------------------------ */
4120    .balign 64
4121.L_OP_SUB_INT: /* 0x91 */
4122/* File: armv5te/OP_SUB_INT.S */
4123/* File: armv5te/binop.S */
4124    /*
4125     * Generic 32-bit binary operation.  Provide an "instr" line that
4126     * specifies an instruction that performs "result = r0 op r1".
4127     * This could be an ARM instruction or a function call.  (If the result
4128     * comes back in a register other than r0, you can override "result".)
4129     *
4130     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4131     * vCC (r1).  Useful for integer division and modulus.  Note that we
4132     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4133     * handles it correctly.
4134     *
4135     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4136     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4137     *      mul-float, div-float, rem-float
4138     */
4139    /* binop vAA, vBB, vCC */
4140    FETCH(r0, 1)                        @ r0<- CCBB
4141    mov     r9, rINST, lsr #8           @ r9<- AA
4142    mov     r3, r0, lsr #8              @ r3<- CC
4143    and     r2, r0, #255                @ r2<- BB
4144    GET_VREG(r1, r3)                    @ r1<- vCC
4145    GET_VREG(r0, r2)                    @ r0<- vBB
4146    .if 0
4147    cmp     r1, #0                      @ is second operand zero?
4148    beq     common_errDivideByZero
4149    .endif
4150
4151    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4152                               @ optional op; may set condition codes
4153    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4155    SET_VREG(r0, r9)               @ vAA<- r0
4156    GOTO_OPCODE(ip)                     @ jump to next instruction
4157    /* 11-14 instructions */
4158
4159
4160
4161/* ------------------------------ */
4162    .balign 64
4163.L_OP_MUL_INT: /* 0x92 */
4164/* File: armv5te/OP_MUL_INT.S */
4165/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4166/* File: armv5te/binop.S */
4167    /*
4168     * Generic 32-bit binary operation.  Provide an "instr" line that
4169     * specifies an instruction that performs "result = r0 op r1".
4170     * This could be an ARM instruction or a function call.  (If the result
4171     * comes back in a register other than r0, you can override "result".)
4172     *
4173     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4174     * vCC (r1).  Useful for integer division and modulus.  Note that we
4175     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4176     * handles it correctly.
4177     *
4178     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4179     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4180     *      mul-float, div-float, rem-float
4181     */
4182    /* binop vAA, vBB, vCC */
4183    FETCH(r0, 1)                        @ r0<- CCBB
4184    mov     r9, rINST, lsr #8           @ r9<- AA
4185    mov     r3, r0, lsr #8              @ r3<- CC
4186    and     r2, r0, #255                @ r2<- BB
4187    GET_VREG(r1, r3)                    @ r1<- vCC
4188    GET_VREG(r0, r2)                    @ r0<- vBB
4189    .if 0
4190    cmp     r1, #0                      @ is second operand zero?
4191    beq     common_errDivideByZero
4192    .endif
4193
4194    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4195                               @ optional op; may set condition codes
4196    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4198    SET_VREG(r0, r9)               @ vAA<- r0
4199    GOTO_OPCODE(ip)                     @ jump to next instruction
4200    /* 11-14 instructions */
4201
4202
4203
4204/* ------------------------------ */
4205    .balign 64
4206.L_OP_DIV_INT: /* 0x93 */
4207/* File: armv5te/OP_DIV_INT.S */
4208/* File: armv5te/binop.S */
4209    /*
4210     * Generic 32-bit binary operation.  Provide an "instr" line that
4211     * specifies an instruction that performs "result = r0 op r1".
4212     * This could be an ARM instruction or a function call.  (If the result
4213     * comes back in a register other than r0, you can override "result".)
4214     *
4215     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4216     * vCC (r1).  Useful for integer division and modulus.  Note that we
4217     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4218     * handles it correctly.
4219     *
4220     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4221     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4222     *      mul-float, div-float, rem-float
4223     */
4224    /* binop vAA, vBB, vCC */
4225    FETCH(r0, 1)                        @ r0<- CCBB
4226    mov     r9, rINST, lsr #8           @ r9<- AA
4227    mov     r3, r0, lsr #8              @ r3<- CC
4228    and     r2, r0, #255                @ r2<- BB
4229    GET_VREG(r1, r3)                    @ r1<- vCC
4230    GET_VREG(r0, r2)                    @ r0<- vBB
4231    .if 1
4232    cmp     r1, #0                      @ is second operand zero?
4233    beq     common_errDivideByZero
4234    .endif
4235
4236    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4237                               @ optional op; may set condition codes
4238    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4240    SET_VREG(r0, r9)               @ vAA<- r0
4241    GOTO_OPCODE(ip)                     @ jump to next instruction
4242    /* 11-14 instructions */
4243
4244
4245
4246/* ------------------------------ */
4247    .balign 64
4248.L_OP_REM_INT: /* 0x94 */
4249/* File: armv5te/OP_REM_INT.S */
4250/* idivmod returns quotient in r0 and remainder in r1 */
4251/* File: armv5te/binop.S */
4252    /*
4253     * Generic 32-bit binary operation.  Provide an "instr" line that
4254     * specifies an instruction that performs "result = r0 op r1".
4255     * This could be an ARM instruction or a function call.  (If the result
4256     * comes back in a register other than r0, you can override "result".)
4257     *
4258     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4259     * vCC (r1).  Useful for integer division and modulus.  Note that we
4260     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4261     * handles it correctly.
4262     *
4263     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4264     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4265     *      mul-float, div-float, rem-float
4266     */
4267    /* binop vAA, vBB, vCC */
4268    FETCH(r0, 1)                        @ r0<- CCBB
4269    mov     r9, rINST, lsr #8           @ r9<- AA
4270    mov     r3, r0, lsr #8              @ r3<- CC
4271    and     r2, r0, #255                @ r2<- BB
4272    GET_VREG(r1, r3)                    @ r1<- vCC
4273    GET_VREG(r0, r2)                    @ r0<- vBB
4274    .if 1
4275    cmp     r1, #0                      @ is second operand zero?
4276    beq     common_errDivideByZero
4277    .endif
4278
4279    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4280                               @ optional op; may set condition codes
4281    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4282    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4283    SET_VREG(r1, r9)               @ vAA<- r1
4284    GOTO_OPCODE(ip)                     @ jump to next instruction
4285    /* 11-14 instructions */
4286
4287
4288
4289/* ------------------------------ */
4290    .balign 64
4291.L_OP_AND_INT: /* 0x95 */
4292/* File: armv5te/OP_AND_INT.S */
4293/* File: armv5te/binop.S */
4294    /*
4295     * Generic 32-bit binary operation.  Provide an "instr" line that
4296     * specifies an instruction that performs "result = r0 op r1".
4297     * This could be an ARM instruction or a function call.  (If the result
4298     * comes back in a register other than r0, you can override "result".)
4299     *
4300     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4301     * vCC (r1).  Useful for integer division and modulus.  Note that we
4302     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4303     * handles it correctly.
4304     *
4305     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4306     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4307     *      mul-float, div-float, rem-float
4308     */
4309    /* binop vAA, vBB, vCC */
4310    FETCH(r0, 1)                        @ r0<- CCBB
4311    mov     r9, rINST, lsr #8           @ r9<- AA
4312    mov     r3, r0, lsr #8              @ r3<- CC
4313    and     r2, r0, #255                @ r2<- BB
4314    GET_VREG(r1, r3)                    @ r1<- vCC
4315    GET_VREG(r0, r2)                    @ r0<- vBB
4316    .if 0
4317    cmp     r1, #0                      @ is second operand zero?
4318    beq     common_errDivideByZero
4319    .endif
4320
4321    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4322                               @ optional op; may set condition codes
4323    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4325    SET_VREG(r0, r9)               @ vAA<- r0
4326    GOTO_OPCODE(ip)                     @ jump to next instruction
4327    /* 11-14 instructions */
4328
4329
4330
4331/* ------------------------------ */
4332    .balign 64
4333.L_OP_OR_INT: /* 0x96 */
4334/* File: armv5te/OP_OR_INT.S */
4335/* File: armv5te/binop.S */
4336    /*
4337     * Generic 32-bit binary operation.  Provide an "instr" line that
4338     * specifies an instruction that performs "result = r0 op r1".
4339     * This could be an ARM instruction or a function call.  (If the result
4340     * comes back in a register other than r0, you can override "result".)
4341     *
4342     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4343     * vCC (r1).  Useful for integer division and modulus.  Note that we
4344     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4345     * handles it correctly.
4346     *
4347     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4348     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4349     *      mul-float, div-float, rem-float
4350     */
4351    /* binop vAA, vBB, vCC */
4352    FETCH(r0, 1)                        @ r0<- CCBB
4353    mov     r9, rINST, lsr #8           @ r9<- AA
4354    mov     r3, r0, lsr #8              @ r3<- CC
4355    and     r2, r0, #255                @ r2<- BB
4356    GET_VREG(r1, r3)                    @ r1<- vCC
4357    GET_VREG(r0, r2)                    @ r0<- vBB
4358    .if 0
4359    cmp     r1, #0                      @ is second operand zero?
4360    beq     common_errDivideByZero
4361    .endif
4362
4363    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4364                               @ optional op; may set condition codes
4365    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4366    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4367    SET_VREG(r0, r9)               @ vAA<- r0
4368    GOTO_OPCODE(ip)                     @ jump to next instruction
4369    /* 11-14 instructions */
4370
4371
4372
4373/* ------------------------------ */
4374    .balign 64
4375.L_OP_XOR_INT: /* 0x97 */
4376/* File: armv5te/OP_XOR_INT.S */
4377/* File: armv5te/binop.S */
4378    /*
4379     * Generic 32-bit binary operation.  Provide an "instr" line that
4380     * specifies an instruction that performs "result = r0 op r1".
4381     * This could be an ARM instruction or a function call.  (If the result
4382     * comes back in a register other than r0, you can override "result".)
4383     *
4384     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4385     * vCC (r1).  Useful for integer division and modulus.  Note that we
4386     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4387     * handles it correctly.
4388     *
4389     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4390     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4391     *      mul-float, div-float, rem-float
4392     */
4393    /* binop vAA, vBB, vCC */
4394    FETCH(r0, 1)                        @ r0<- CCBB
4395    mov     r9, rINST, lsr #8           @ r9<- AA
4396    mov     r3, r0, lsr #8              @ r3<- CC
4397    and     r2, r0, #255                @ r2<- BB
4398    GET_VREG(r1, r3)                    @ r1<- vCC
4399    GET_VREG(r0, r2)                    @ r0<- vBB
4400    .if 0
4401    cmp     r1, #0                      @ is second operand zero?
4402    beq     common_errDivideByZero
4403    .endif
4404
4405    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4406                               @ optional op; may set condition codes
4407    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4409    SET_VREG(r0, r9)               @ vAA<- r0
4410    GOTO_OPCODE(ip)                     @ jump to next instruction
4411    /* 11-14 instructions */
4412
4413
4414
4415/* ------------------------------ */
4416    .balign 64
4417.L_OP_SHL_INT: /* 0x98 */
4418/* File: armv5te/OP_SHL_INT.S */
4419/* File: armv5te/binop.S */
4420    /*
4421     * Generic 32-bit binary operation.  Provide an "instr" line that
4422     * specifies an instruction that performs "result = r0 op r1".
4423     * This could be an ARM instruction or a function call.  (If the result
4424     * comes back in a register other than r0, you can override "result".)
4425     *
4426     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4427     * vCC (r1).  Useful for integer division and modulus.  Note that we
4428     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4429     * handles it correctly.
4430     *
4431     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4432     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4433     *      mul-float, div-float, rem-float
4434     */
4435    /* binop vAA, vBB, vCC */
4436    FETCH(r0, 1)                        @ r0<- CCBB
4437    mov     r9, rINST, lsr #8           @ r9<- AA
4438    mov     r3, r0, lsr #8              @ r3<- CC
4439    and     r2, r0, #255                @ r2<- BB
4440    GET_VREG(r1, r3)                    @ r1<- vCC
4441    GET_VREG(r0, r2)                    @ r0<- vBB
4442    .if 0
4443    cmp     r1, #0                      @ is second operand zero?
4444    beq     common_errDivideByZero
4445    .endif
4446
4447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4448    and     r1, r1, #31                           @ optional op; may set condition codes
4449    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4450    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4451    SET_VREG(r0, r9)               @ vAA<- r0
4452    GOTO_OPCODE(ip)                     @ jump to next instruction
4453    /* 11-14 instructions */
4454
4455
4456
4457/* ------------------------------ */
4458    .balign 64
4459.L_OP_SHR_INT: /* 0x99 */
4460/* File: armv5te/OP_SHR_INT.S */
4461/* File: armv5te/binop.S */
4462    /*
4463     * Generic 32-bit binary operation.  Provide an "instr" line that
4464     * specifies an instruction that performs "result = r0 op r1".
4465     * This could be an ARM instruction or a function call.  (If the result
4466     * comes back in a register other than r0, you can override "result".)
4467     *
4468     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4469     * vCC (r1).  Useful for integer division and modulus.  Note that we
4470     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4471     * handles it correctly.
4472     *
4473     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4474     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4475     *      mul-float, div-float, rem-float
4476     */
4477    /* binop vAA, vBB, vCC */
4478    FETCH(r0, 1)                        @ r0<- CCBB
4479    mov     r9, rINST, lsr #8           @ r9<- AA
4480    mov     r3, r0, lsr #8              @ r3<- CC
4481    and     r2, r0, #255                @ r2<- BB
4482    GET_VREG(r1, r3)                    @ r1<- vCC
4483    GET_VREG(r0, r2)                    @ r0<- vBB
4484    .if 0
4485    cmp     r1, #0                      @ is second operand zero?
4486    beq     common_errDivideByZero
4487    .endif
4488
4489    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4490    and     r1, r1, #31                           @ optional op; may set condition codes
4491    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4492    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4493    SET_VREG(r0, r9)               @ vAA<- r0
4494    GOTO_OPCODE(ip)                     @ jump to next instruction
4495    /* 11-14 instructions */
4496
4497
4498
4499/* ------------------------------ */
4500    .balign 64
4501.L_OP_USHR_INT: /* 0x9a */
4502/* File: armv5te/OP_USHR_INT.S */
4503/* File: armv5te/binop.S */
4504    /*
4505     * Generic 32-bit binary operation.  Provide an "instr" line that
4506     * specifies an instruction that performs "result = r0 op r1".
4507     * This could be an ARM instruction or a function call.  (If the result
4508     * comes back in a register other than r0, you can override "result".)
4509     *
4510     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4511     * vCC (r1).  Useful for integer division and modulus.  Note that we
4512     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4513     * handles it correctly.
4514     *
4515     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4516     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4517     *      mul-float, div-float, rem-float
4518     */
4519    /* binop vAA, vBB, vCC */
4520    FETCH(r0, 1)                        @ r0<- CCBB
4521    mov     r9, rINST, lsr #8           @ r9<- AA
4522    mov     r3, r0, lsr #8              @ r3<- CC
4523    and     r2, r0, #255                @ r2<- BB
4524    GET_VREG(r1, r3)                    @ r1<- vCC
4525    GET_VREG(r0, r2)                    @ r0<- vBB
4526    .if 0
4527    cmp     r1, #0                      @ is second operand zero?
4528    beq     common_errDivideByZero
4529    .endif
4530
4531    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4532    and     r1, r1, #31                           @ optional op; may set condition codes
4533    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4534    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4535    SET_VREG(r0, r9)               @ vAA<- r0
4536    GOTO_OPCODE(ip)                     @ jump to next instruction
4537    /* 11-14 instructions */
4538
4539
4540
4541/* ------------------------------ */
4542    .balign 64
4543.L_OP_ADD_LONG: /* 0x9b */
4544/* File: armv5te/OP_ADD_LONG.S */
4545/* File: armv5te/binopWide.S */
4546    /*
4547     * Generic 64-bit binary operation.  Provide an "instr" line that
4548     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4549     * This could be an ARM instruction or a function call.  (If the result
4550     * comes back in a register other than r0, you can override "result".)
4551     *
4552     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4553     * vCC (r1).  Useful for integer division and modulus.
4554     *
4555     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4556     *      xor-long, add-double, sub-double, mul-double, div-double,
4557     *      rem-double
4558     *
4559     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4560     */
4561    /* binop vAA, vBB, vCC */
4562    FETCH(r0, 1)                        @ r0<- CCBB
4563    mov     r9, rINST, lsr #8           @ r9<- AA
4564    and     r2, r0, #255                @ r2<- BB
4565    mov     r3, r0, lsr #8              @ r3<- CC
4566    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4567    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4568    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4569    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4570    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4571    .if 0
4572    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4573    beq     common_errDivideByZero
4574    .endif
4575    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4576
4577    adds    r0, r0, r2                           @ optional op; may set condition codes
4578    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4580    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4581    GOTO_OPCODE(ip)                     @ jump to next instruction
4582    /* 14-17 instructions */
4583
4584
4585
4586/* ------------------------------ */
4587    .balign 64
4588.L_OP_SUB_LONG: /* 0x9c */
4589/* File: armv5te/OP_SUB_LONG.S */
4590/* File: armv5te/binopWide.S */
4591    /*
4592     * Generic 64-bit binary operation.  Provide an "instr" line that
4593     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4594     * This could be an ARM instruction or a function call.  (If the result
4595     * comes back in a register other than r0, you can override "result".)
4596     *
4597     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4598     * vCC (r1).  Useful for integer division and modulus.
4599     *
4600     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4601     *      xor-long, add-double, sub-double, mul-double, div-double,
4602     *      rem-double
4603     *
4604     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4605     */
4606    /* binop vAA, vBB, vCC */
4607    FETCH(r0, 1)                        @ r0<- CCBB
4608    mov     r9, rINST, lsr #8           @ r9<- AA
4609    and     r2, r0, #255                @ r2<- BB
4610    mov     r3, r0, lsr #8              @ r3<- CC
4611    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4612    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4613    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4614    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4615    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4616    .if 0
4617    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4618    beq     common_errDivideByZero
4619    .endif
4620    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4621
4622    subs    r0, r0, r2                           @ optional op; may set condition codes
4623    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4625    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4626    GOTO_OPCODE(ip)                     @ jump to next instruction
4627    /* 14-17 instructions */
4628
4629
4630
4631/* ------------------------------ */
4632    .balign 64
4633.L_OP_MUL_LONG: /* 0x9d */
4634/* File: armv5te/OP_MUL_LONG.S */
4635    /*
4636     * Signed 64-bit integer multiply.
4637     *
4638     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4639     *        WX
4640     *      x YZ
4641     *  --------
4642     *     ZW ZX
4643     *  YW YX
4644     *
4645     * The low word of the result holds ZX, the high word holds
4646     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4647     * it doesn't fit in the low 64 bits.
4648     *
4649     * Unlike most ARM math operations, multiply instructions have
4650     * restrictions on using the same register more than once (Rd and Rm
4651     * cannot be the same).
4652     */
4653    /* mul-long vAA, vBB, vCC */
4654    FETCH(r0, 1)                        @ r0<- CCBB
4655    and     r2, r0, #255                @ r2<- BB
4656    mov     r3, r0, lsr #8              @ r3<- CC
4657    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4658    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4659    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4660    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4661    mul     ip, r2, r1                  @  ip<- ZxW
4662    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4663    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4664    mov     r0, rINST, lsr #8           @ r0<- AA
4665    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4666    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4667    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4668    b       .LOP_MUL_LONG_finish
4669
4670/* ------------------------------ */
4671    .balign 64
4672.L_OP_DIV_LONG: /* 0x9e */
4673/* File: armv5te/OP_DIV_LONG.S */
4674/* File: armv5te/binopWide.S */
4675    /*
4676     * Generic 64-bit binary operation.  Provide an "instr" line that
4677     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4678     * This could be an ARM instruction or a function call.  (If the result
4679     * comes back in a register other than r0, you can override "result".)
4680     *
4681     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4682     * vCC (r1).  Useful for integer division and modulus.
4683     *
4684     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4685     *      xor-long, add-double, sub-double, mul-double, div-double,
4686     *      rem-double
4687     *
4688     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4689     */
4690    /* binop vAA, vBB, vCC */
4691    FETCH(r0, 1)                        @ r0<- CCBB
4692    mov     r9, rINST, lsr #8           @ r9<- AA
4693    and     r2, r0, #255                @ r2<- BB
4694    mov     r3, r0, lsr #8              @ r3<- CC
4695    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4696    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4697    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4698    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4699    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4700    .if 1
4701    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4702    beq     common_errDivideByZero
4703    .endif
4704    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4705
4706                               @ optional op; may set condition codes
4707    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4708    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4709    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4710    GOTO_OPCODE(ip)                     @ jump to next instruction
4711    /* 14-17 instructions */
4712
4713
4714
4715/* ------------------------------ */
4716    .balign 64
4717.L_OP_REM_LONG: /* 0x9f */
4718/* File: armv5te/OP_REM_LONG.S */
4719/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4720/* File: armv5te/binopWide.S */
4721    /*
4722     * Generic 64-bit binary operation.  Provide an "instr" line that
4723     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4724     * This could be an ARM instruction or a function call.  (If the result
4725     * comes back in a register other than r0, you can override "result".)
4726     *
4727     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4728     * vCC (r1).  Useful for integer division and modulus.
4729     *
4730     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4731     *      xor-long, add-double, sub-double, mul-double, div-double,
4732     *      rem-double
4733     *
4734     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4735     */
4736    /* binop vAA, vBB, vCC */
4737    FETCH(r0, 1)                        @ r0<- CCBB
4738    mov     r9, rINST, lsr #8           @ r9<- AA
4739    and     r2, r0, #255                @ r2<- BB
4740    mov     r3, r0, lsr #8              @ r3<- CC
4741    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4742    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4743    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4744    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4745    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4746    .if 1
4747    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4748    beq     common_errDivideByZero
4749    .endif
4750    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4751
4752                               @ optional op; may set condition codes
4753    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4755    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4756    GOTO_OPCODE(ip)                     @ jump to next instruction
4757    /* 14-17 instructions */
4758
4759
4760
4761/* ------------------------------ */
4762    .balign 64
4763.L_OP_AND_LONG: /* 0xa0 */
4764/* File: armv5te/OP_AND_LONG.S */
4765/* File: armv5te/binopWide.S */
4766    /*
4767     * Generic 64-bit binary operation.  Provide an "instr" line that
4768     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4769     * This could be an ARM instruction or a function call.  (If the result
4770     * comes back in a register other than r0, you can override "result".)
4771     *
4772     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4773     * vCC (r1).  Useful for integer division and modulus.
4774     *
4775     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4776     *      xor-long, add-double, sub-double, mul-double, div-double,
4777     *      rem-double
4778     *
4779     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4780     */
4781    /* binop vAA, vBB, vCC */
4782    FETCH(r0, 1)                        @ r0<- CCBB
4783    mov     r9, rINST, lsr #8           @ r9<- AA
4784    and     r2, r0, #255                @ r2<- BB
4785    mov     r3, r0, lsr #8              @ r3<- CC
4786    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4787    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4788    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4789    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4790    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4791    .if 0
4792    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4793    beq     common_errDivideByZero
4794    .endif
4795    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4796
4797    and     r0, r0, r2                           @ optional op; may set condition codes
4798    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4800    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4801    GOTO_OPCODE(ip)                     @ jump to next instruction
4802    /* 14-17 instructions */
4803
4804
4805
4806/* ------------------------------ */
4807    .balign 64
4808.L_OP_OR_LONG: /* 0xa1 */
4809/* File: armv5te/OP_OR_LONG.S */
4810/* File: armv5te/binopWide.S */
4811    /*
4812     * Generic 64-bit binary operation.  Provide an "instr" line that
4813     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4814     * This could be an ARM instruction or a function call.  (If the result
4815     * comes back in a register other than r0, you can override "result".)
4816     *
4817     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4818     * vCC (r1).  Useful for integer division and modulus.
4819     *
4820     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4821     *      xor-long, add-double, sub-double, mul-double, div-double,
4822     *      rem-double
4823     *
4824     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4825     */
4826    /* binop vAA, vBB, vCC */
4827    FETCH(r0, 1)                        @ r0<- CCBB
4828    mov     r9, rINST, lsr #8           @ r9<- AA
4829    and     r2, r0, #255                @ r2<- BB
4830    mov     r3, r0, lsr #8              @ r3<- CC
4831    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4832    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4833    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4834    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4835    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4836    .if 0
4837    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4838    beq     common_errDivideByZero
4839    .endif
4840    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4841
4842    orr     r0, r0, r2                           @ optional op; may set condition codes
4843    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4845    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4846    GOTO_OPCODE(ip)                     @ jump to next instruction
4847    /* 14-17 instructions */
4848
4849
4850
4851/* ------------------------------ */
4852    .balign 64
4853.L_OP_XOR_LONG: /* 0xa2 */
4854/* File: armv5te/OP_XOR_LONG.S */
4855/* File: armv5te/binopWide.S */
4856    /*
4857     * Generic 64-bit binary operation.  Provide an "instr" line that
4858     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4859     * This could be an ARM instruction or a function call.  (If the result
4860     * comes back in a register other than r0, you can override "result".)
4861     *
4862     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4863     * vCC (r1).  Useful for integer division and modulus.
4864     *
4865     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4866     *      xor-long, add-double, sub-double, mul-double, div-double,
4867     *      rem-double
4868     *
4869     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4870     */
4871    /* binop vAA, vBB, vCC */
4872    FETCH(r0, 1)                        @ r0<- CCBB
4873    mov     r9, rINST, lsr #8           @ r9<- AA
4874    and     r2, r0, #255                @ r2<- BB
4875    mov     r3, r0, lsr #8              @ r3<- CC
4876    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4877    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4878    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4879    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4880    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4881    .if 0
4882    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4883    beq     common_errDivideByZero
4884    .endif
4885    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4886
4887    eor     r0, r0, r2                           @ optional op; may set condition codes
4888    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4890    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4891    GOTO_OPCODE(ip)                     @ jump to next instruction
4892    /* 14-17 instructions */
4893
4894
4895
4896/* ------------------------------ */
4897    .balign 64
4898.L_OP_SHL_LONG: /* 0xa3 */
4899/* File: armv5te/OP_SHL_LONG.S */
4900    /*
4901     * Long integer shift.  This is different from the generic 32/64-bit
4902     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4903     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4904     * 6 bits of the shift distance.
4905     */
4906    /* shl-long vAA, vBB, vCC */
4907    FETCH(r0, 1)                        @ r0<- CCBB
4908    mov     r9, rINST, lsr #8           @ r9<- AA
4909    and     r3, r0, #255                @ r3<- BB
4910    mov     r0, r0, lsr #8              @ r0<- CC
4911    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4912    GET_VREG(r2, r0)                    @ r2<- vCC
4913    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4914    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4915    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4916
4917    mov     r1, r1, asl r2              @  r1<- r1 << r2
4918    rsb     r3, r2, #32                 @  r3<- 32 - r2
4919    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4920    subs    ip, r2, #32                 @  ip<- r2 - 32
4921    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4923    b       .LOP_SHL_LONG_finish
4924
4925/* ------------------------------ */
4926    .balign 64
4927.L_OP_SHR_LONG: /* 0xa4 */
4928/* File: armv5te/OP_SHR_LONG.S */
4929    /*
4930     * Long integer shift.  This is different from the generic 32/64-bit
4931     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4932     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4933     * 6 bits of the shift distance.
4934     */
4935    /* shr-long vAA, vBB, vCC */
4936    FETCH(r0, 1)                        @ r0<- CCBB
4937    mov     r9, rINST, lsr #8           @ r9<- AA
4938    and     r3, r0, #255                @ r3<- BB
4939    mov     r0, r0, lsr #8              @ r0<- CC
4940    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4941    GET_VREG(r2, r0)                    @ r2<- vCC
4942    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4943    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4944    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4945
4946    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4947    rsb     r3, r2, #32                 @  r3<- 32 - r2
4948    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4949    subs    ip, r2, #32                 @  ip<- r2 - 32
4950    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4952    b       .LOP_SHR_LONG_finish
4953
4954/* ------------------------------ */
4955    .balign 64
4956.L_OP_USHR_LONG: /* 0xa5 */
4957/* File: armv5te/OP_USHR_LONG.S */
4958    /*
4959     * Long integer shift.  This is different from the generic 32/64-bit
4960     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4961     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4962     * 6 bits of the shift distance.
4963     */
4964    /* ushr-long vAA, vBB, vCC */
4965    FETCH(r0, 1)                        @ r0<- CCBB
4966    mov     r9, rINST, lsr #8           @ r9<- AA
4967    and     r3, r0, #255                @ r3<- BB
4968    mov     r0, r0, lsr #8              @ r0<- CC
4969    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4970    GET_VREG(r2, r0)                    @ r2<- vCC
4971    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4972    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4973    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4974
4975    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4976    rsb     r3, r2, #32                 @  r3<- 32 - r2
4977    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4978    subs    ip, r2, #32                 @  ip<- r2 - 32
4979    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4980    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4981    b       .LOP_USHR_LONG_finish
4982
4983/* ------------------------------ */
4984    .balign 64
4985.L_OP_ADD_FLOAT: /* 0xa6 */
4986/* File: arm-vfp/OP_ADD_FLOAT.S */
4987/* File: arm-vfp/fbinop.S */
4988    /*
4989     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4990     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4991     * use the "softfp" ABI, this must be an instruction, not a function call.
4992     *
4993     * For: add-float, sub-float, mul-float, div-float
4994     */
4995    /* floatop vAA, vBB, vCC */
4996    FETCH(r0, 1)                        @ r0<- CCBB
4997    mov     r9, rINST, lsr #8           @ r9<- AA
4998    mov     r3, r0, lsr #8              @ r3<- CC
4999    and     r2, r0, #255                @ r2<- BB
5000    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5001    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5002    flds    s1, [r3]                    @ s1<- vCC
5003    flds    s0, [r2]                    @ s0<- vBB
5004
5005    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5006    fadds   s2, s0, s1                              @ s2<- op
5007    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5008    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5009    fsts    s2, [r9]                    @ vAA<- s2
5010    GOTO_OPCODE(ip)                     @ jump to next instruction
5011
5012
5013/* ------------------------------ */
5014    .balign 64
5015.L_OP_SUB_FLOAT: /* 0xa7 */
5016/* File: arm-vfp/OP_SUB_FLOAT.S */
5017/* File: arm-vfp/fbinop.S */
5018    /*
5019     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5020     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5021     * use the "softfp" ABI, this must be an instruction, not a function call.
5022     *
5023     * For: add-float, sub-float, mul-float, div-float
5024     */
5025    /* floatop vAA, vBB, vCC */
5026    FETCH(r0, 1)                        @ r0<- CCBB
5027    mov     r9, rINST, lsr #8           @ r9<- AA
5028    mov     r3, r0, lsr #8              @ r3<- CC
5029    and     r2, r0, #255                @ r2<- BB
5030    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5031    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5032    flds    s1, [r3]                    @ s1<- vCC
5033    flds    s0, [r2]                    @ s0<- vBB
5034
5035    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5036    fsubs   s2, s0, s1                              @ s2<- op
5037    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5038    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5039    fsts    s2, [r9]                    @ vAA<- s2
5040    GOTO_OPCODE(ip)                     @ jump to next instruction
5041
5042
5043/* ------------------------------ */
5044    .balign 64
5045.L_OP_MUL_FLOAT: /* 0xa8 */
5046/* File: arm-vfp/OP_MUL_FLOAT.S */
5047/* File: arm-vfp/fbinop.S */
5048    /*
5049     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5050     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5051     * use the "softfp" ABI, this must be an instruction, not a function call.
5052     *
5053     * For: add-float, sub-float, mul-float, div-float
5054     */
5055    /* floatop vAA, vBB, vCC */
5056    FETCH(r0, 1)                        @ r0<- CCBB
5057    mov     r9, rINST, lsr #8           @ r9<- AA
5058    mov     r3, r0, lsr #8              @ r3<- CC
5059    and     r2, r0, #255                @ r2<- BB
5060    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5061    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5062    flds    s1, [r3]                    @ s1<- vCC
5063    flds    s0, [r2]                    @ s0<- vBB
5064
5065    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5066    fmuls   s2, s0, s1                              @ s2<- op
5067    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5068    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5069    fsts    s2, [r9]                    @ vAA<- s2
5070    GOTO_OPCODE(ip)                     @ jump to next instruction
5071
5072
5073/* ------------------------------ */
5074    .balign 64
5075.L_OP_DIV_FLOAT: /* 0xa9 */
5076/* File: arm-vfp/OP_DIV_FLOAT.S */
5077/* File: arm-vfp/fbinop.S */
5078    /*
5079     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5080     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5081     * use the "softfp" ABI, this must be an instruction, not a function call.
5082     *
5083     * For: add-float, sub-float, mul-float, div-float
5084     */
5085    /* floatop vAA, vBB, vCC */
5086    FETCH(r0, 1)                        @ r0<- CCBB
5087    mov     r9, rINST, lsr #8           @ r9<- AA
5088    mov     r3, r0, lsr #8              @ r3<- CC
5089    and     r2, r0, #255                @ r2<- BB
5090    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5091    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5092    flds    s1, [r3]                    @ s1<- vCC
5093    flds    s0, [r2]                    @ s0<- vBB
5094
5095    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5096    fdivs   s2, s0, s1                              @ s2<- op
5097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5098    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5099    fsts    s2, [r9]                    @ vAA<- s2
5100    GOTO_OPCODE(ip)                     @ jump to next instruction
5101
5102
5103/* ------------------------------ */
5104    .balign 64
5105.L_OP_REM_FLOAT: /* 0xaa */
5106/* File: armv5te/OP_REM_FLOAT.S */
5107/* EABI doesn't define a float remainder function, but libm does */
5108/* File: armv5te/binop.S */
5109    /*
5110     * Generic 32-bit binary operation.  Provide an "instr" line that
5111     * specifies an instruction that performs "result = r0 op r1".
5112     * This could be an ARM instruction or a function call.  (If the result
5113     * comes back in a register other than r0, you can override "result".)
5114     *
5115     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5116     * vCC (r1).  Useful for integer division and modulus.  Note that we
5117     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5118     * handles it correctly.
5119     *
5120     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5121     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5122     *      mul-float, div-float, rem-float
5123     */
5124    /* binop vAA, vBB, vCC */
5125    FETCH(r0, 1)                        @ r0<- CCBB
5126    mov     r9, rINST, lsr #8           @ r9<- AA
5127    mov     r3, r0, lsr #8              @ r3<- CC
5128    and     r2, r0, #255                @ r2<- BB
5129    GET_VREG(r1, r3)                    @ r1<- vCC
5130    GET_VREG(r0, r2)                    @ r0<- vBB
5131    .if 0
5132    cmp     r1, #0                      @ is second operand zero?
5133    beq     common_errDivideByZero
5134    .endif
5135
5136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5137                               @ optional op; may set condition codes
5138    bl      fmodf                              @ r0<- op, r0-r3 changed
5139    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5140    SET_VREG(r0, r9)               @ vAA<- r0
5141    GOTO_OPCODE(ip)                     @ jump to next instruction
5142    /* 11-14 instructions */
5143
5144
5145
5146/* ------------------------------ */
5147    .balign 64
5148.L_OP_ADD_DOUBLE: /* 0xab */
5149/* File: arm-vfp/OP_ADD_DOUBLE.S */
5150/* File: arm-vfp/fbinopWide.S */
5151    /*
5152     * Generic 64-bit double-precision floating point binary operation.
5153     * Provide an "instr" line that specifies an instruction that performs
5154     * "d2 = d0 op d1".
5155     *
5156     * for: add-double, sub-double, mul-double, div-double
5157     */
5158    /* doubleop vAA, vBB, vCC */
5159    FETCH(r0, 1)                        @ r0<- CCBB
5160    mov     r9, rINST, lsr #8           @ r9<- AA
5161    mov     r3, r0, lsr #8              @ r3<- CC
5162    and     r2, r0, #255                @ r2<- BB
5163    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5164    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5165    fldd    d1, [r3]                    @ d1<- vCC
5166    fldd    d0, [r2]                    @ d0<- vBB
5167
5168    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5169    faddd   d2, d0, d1                              @ s2<- op
5170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5171    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5172    fstd    d2, [r9]                    @ vAA<- d2
5173    GOTO_OPCODE(ip)                     @ jump to next instruction
5174
5175
5176/* ------------------------------ */
5177    .balign 64
5178.L_OP_SUB_DOUBLE: /* 0xac */
5179/* File: arm-vfp/OP_SUB_DOUBLE.S */
5180/* File: arm-vfp/fbinopWide.S */
5181    /*
5182     * Generic 64-bit double-precision floating point binary operation.
5183     * Provide an "instr" line that specifies an instruction that performs
5184     * "d2 = d0 op d1".
5185     *
5186     * for: add-double, sub-double, mul-double, div-double
5187     */
5188    /* doubleop vAA, vBB, vCC */
5189    FETCH(r0, 1)                        @ r0<- CCBB
5190    mov     r9, rINST, lsr #8           @ r9<- AA
5191    mov     r3, r0, lsr #8              @ r3<- CC
5192    and     r2, r0, #255                @ r2<- BB
5193    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5194    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5195    fldd    d1, [r3]                    @ d1<- vCC
5196    fldd    d0, [r2]                    @ d0<- vBB
5197
5198    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5199    fsubd   d2, d0, d1                              @ s2<- op
5200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5201    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5202    fstd    d2, [r9]                    @ vAA<- d2
5203    GOTO_OPCODE(ip)                     @ jump to next instruction
5204
5205
5206/* ------------------------------ */
5207    .balign 64
5208.L_OP_MUL_DOUBLE: /* 0xad */
5209/* File: arm-vfp/OP_MUL_DOUBLE.S */
5210/* File: arm-vfp/fbinopWide.S */
5211    /*
5212     * Generic 64-bit double-precision floating point binary operation.
5213     * Provide an "instr" line that specifies an instruction that performs
5214     * "d2 = d0 op d1".
5215     *
5216     * for: add-double, sub-double, mul-double, div-double
5217     */
5218    /* doubleop vAA, vBB, vCC */
5219    FETCH(r0, 1)                        @ r0<- CCBB
5220    mov     r9, rINST, lsr #8           @ r9<- AA
5221    mov     r3, r0, lsr #8              @ r3<- CC
5222    and     r2, r0, #255                @ r2<- BB
5223    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5224    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5225    fldd    d1, [r3]                    @ d1<- vCC
5226    fldd    d0, [r2]                    @ d0<- vBB
5227
5228    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5229    fmuld   d2, d0, d1                              @ s2<- op
5230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5231    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5232    fstd    d2, [r9]                    @ vAA<- d2
5233    GOTO_OPCODE(ip)                     @ jump to next instruction
5234
5235
5236/* ------------------------------ */
5237    .balign 64
5238.L_OP_DIV_DOUBLE: /* 0xae */
5239/* File: arm-vfp/OP_DIV_DOUBLE.S */
5240/* File: arm-vfp/fbinopWide.S */
5241    /*
5242     * Generic 64-bit double-precision floating point binary operation.
5243     * Provide an "instr" line that specifies an instruction that performs
5244     * "d2 = d0 op d1".
5245     *
5246     * for: add-double, sub-double, mul-double, div-double
5247     */
5248    /* doubleop vAA, vBB, vCC */
5249    FETCH(r0, 1)                        @ r0<- CCBB
5250    mov     r9, rINST, lsr #8           @ r9<- AA
5251    mov     r3, r0, lsr #8              @ r3<- CC
5252    and     r2, r0, #255                @ r2<- BB
5253    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5254    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5255    fldd    d1, [r3]                    @ d1<- vCC
5256    fldd    d0, [r2]                    @ d0<- vBB
5257
5258    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5259    fdivd   d2, d0, d1                              @ s2<- op
5260    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5261    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5262    fstd    d2, [r9]                    @ vAA<- d2
5263    GOTO_OPCODE(ip)                     @ jump to next instruction
5264
5265
5266/* ------------------------------ */
5267    .balign 64
5268.L_OP_REM_DOUBLE: /* 0xaf */
5269/* File: armv5te/OP_REM_DOUBLE.S */
5270/* EABI doesn't define a double remainder function, but libm does */
5271/* File: armv5te/binopWide.S */
5272    /*
5273     * Generic 64-bit binary operation.  Provide an "instr" line that
5274     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5275     * This could be an ARM instruction or a function call.  (If the result
5276     * comes back in a register other than r0, you can override "result".)
5277     *
5278     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5279     * vCC (r1).  Useful for integer division and modulus.
5280     *
5281     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5282     *      xor-long, add-double, sub-double, mul-double, div-double,
5283     *      rem-double
5284     *
5285     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5286     */
5287    /* binop vAA, vBB, vCC */
5288    FETCH(r0, 1)                        @ r0<- CCBB
5289    mov     r9, rINST, lsr #8           @ r9<- AA
5290    and     r2, r0, #255                @ r2<- BB
5291    mov     r3, r0, lsr #8              @ r3<- CC
5292    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5293    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5294    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5295    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5296    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5297    .if 0
5298    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5299    beq     common_errDivideByZero
5300    .endif
5301    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5302
5303                               @ optional op; may set condition codes
5304    bl      fmod                              @ result<- op, r0-r3 changed
5305    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5306    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5307    GOTO_OPCODE(ip)                     @ jump to next instruction
5308    /* 14-17 instructions */
5309
5310
5311
5312/* ------------------------------ */
5313    .balign 64
5314.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5315/* File: armv5te/OP_ADD_INT_2ADDR.S */
5316/* File: armv5te/binop2addr.S */
5317    /*
5318     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5319     * that specifies an instruction that performs "result = r0 op r1".
5320     * This could be an ARM instruction or a function call.  (If the result
5321     * comes back in a register other than r0, you can override "result".)
5322     *
5323     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5324     * vCC (r1).  Useful for integer division and modulus.
5325     *
5326     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5327     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5328     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5329     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5330     */
5331    /* binop/2addr vA, vB */
5332    mov     r9, rINST, lsr #8           @ r9<- A+
5333    mov     r3, rINST, lsr #12          @ r3<- B
5334    and     r9, r9, #15
5335    GET_VREG(r1, r3)                    @ r1<- vB
5336    GET_VREG(r0, r9)                    @ r0<- vA
5337    .if 0
5338    cmp     r1, #0                      @ is second operand zero?
5339    beq     common_errDivideByZero
5340    .endif
5341    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5342
5343                               @ optional op; may set condition codes
5344    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5346    SET_VREG(r0, r9)               @ vAA<- r0
5347    GOTO_OPCODE(ip)                     @ jump to next instruction
5348    /* 10-13 instructions */
5349
5350
5351
5352/* ------------------------------ */
5353    .balign 64
5354.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5355/* File: armv5te/OP_SUB_INT_2ADDR.S */
5356/* File: armv5te/binop2addr.S */
5357    /*
5358     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5359     * that specifies an instruction that performs "result = r0 op r1".
5360     * This could be an ARM instruction or a function call.  (If the result
5361     * comes back in a register other than r0, you can override "result".)
5362     *
5363     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5364     * vCC (r1).  Useful for integer division and modulus.
5365     *
5366     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5367     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5368     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5369     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5370     */
5371    /* binop/2addr vA, vB */
5372    mov     r9, rINST, lsr #8           @ r9<- A+
5373    mov     r3, rINST, lsr #12          @ r3<- B
5374    and     r9, r9, #15
5375    GET_VREG(r1, r3)                    @ r1<- vB
5376    GET_VREG(r0, r9)                    @ r0<- vA
5377    .if 0
5378    cmp     r1, #0                      @ is second operand zero?
5379    beq     common_errDivideByZero
5380    .endif
5381    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5382
5383                               @ optional op; may set condition codes
5384    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5385    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5386    SET_VREG(r0, r9)               @ vAA<- r0
5387    GOTO_OPCODE(ip)                     @ jump to next instruction
5388    /* 10-13 instructions */
5389
5390
5391
5392/* ------------------------------ */
5393    .balign 64
5394.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5395/* File: armv5te/OP_MUL_INT_2ADDR.S */
5396/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5397/* File: armv5te/binop2addr.S */
5398    /*
5399     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5400     * that specifies an instruction that performs "result = r0 op r1".
5401     * This could be an ARM instruction or a function call.  (If the result
5402     * comes back in a register other than r0, you can override "result".)
5403     *
5404     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5405     * vCC (r1).  Useful for integer division and modulus.
5406     *
5407     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5408     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5409     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5410     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5411     */
5412    /* binop/2addr vA, vB */
5413    mov     r9, rINST, lsr #8           @ r9<- A+
5414    mov     r3, rINST, lsr #12          @ r3<- B
5415    and     r9, r9, #15
5416    GET_VREG(r1, r3)                    @ r1<- vB
5417    GET_VREG(r0, r9)                    @ r0<- vA
5418    .if 0
5419    cmp     r1, #0                      @ is second operand zero?
5420    beq     common_errDivideByZero
5421    .endif
5422    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5423
5424                               @ optional op; may set condition codes
5425    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5426    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5427    SET_VREG(r0, r9)               @ vAA<- r0
5428    GOTO_OPCODE(ip)                     @ jump to next instruction
5429    /* 10-13 instructions */
5430
5431
5432
5433/* ------------------------------ */
5434    .balign 64
5435.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5436/* File: armv5te/OP_DIV_INT_2ADDR.S */
5437/* File: armv5te/binop2addr.S */
5438    /*
5439     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5440     * that specifies an instruction that performs "result = r0 op r1".
5441     * This could be an ARM instruction or a function call.  (If the result
5442     * comes back in a register other than r0, you can override "result".)
5443     *
5444     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5445     * vCC (r1).  Useful for integer division and modulus.
5446     *
5447     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5448     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5449     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5450     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5451     */
5452    /* binop/2addr vA, vB */
5453    mov     r9, rINST, lsr #8           @ r9<- A+
5454    mov     r3, rINST, lsr #12          @ r3<- B
5455    and     r9, r9, #15
5456    GET_VREG(r1, r3)                    @ r1<- vB
5457    GET_VREG(r0, r9)                    @ r0<- vA
5458    .if 1
5459    cmp     r1, #0                      @ is second operand zero?
5460    beq     common_errDivideByZero
5461    .endif
5462    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5463
5464                               @ optional op; may set condition codes
5465    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5466    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5467    SET_VREG(r0, r9)               @ vAA<- r0
5468    GOTO_OPCODE(ip)                     @ jump to next instruction
5469    /* 10-13 instructions */
5470
5471
5472
5473/* ------------------------------ */
5474    .balign 64
5475.L_OP_REM_INT_2ADDR: /* 0xb4 */
5476/* File: armv5te/OP_REM_INT_2ADDR.S */
5477/* idivmod returns quotient in r0 and remainder in r1 */
5478/* File: armv5te/binop2addr.S */
5479    /*
5480     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5481     * that specifies an instruction that performs "result = r0 op r1".
5482     * This could be an ARM instruction or a function call.  (If the result
5483     * comes back in a register other than r0, you can override "result".)
5484     *
5485     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5486     * vCC (r1).  Useful for integer division and modulus.
5487     *
5488     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5489     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5490     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5491     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5492     */
5493    /* binop/2addr vA, vB */
5494    mov     r9, rINST, lsr #8           @ r9<- A+
5495    mov     r3, rINST, lsr #12          @ r3<- B
5496    and     r9, r9, #15
5497    GET_VREG(r1, r3)                    @ r1<- vB
5498    GET_VREG(r0, r9)                    @ r0<- vA
5499    .if 1
5500    cmp     r1, #0                      @ is second operand zero?
5501    beq     common_errDivideByZero
5502    .endif
5503    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5504
5505                               @ optional op; may set condition codes
5506    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5507    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5508    SET_VREG(r1, r9)               @ vAA<- r1
5509    GOTO_OPCODE(ip)                     @ jump to next instruction
5510    /* 10-13 instructions */
5511
5512
5513
5514/* ------------------------------ */
5515    .balign 64
5516.L_OP_AND_INT_2ADDR: /* 0xb5 */
5517/* File: armv5te/OP_AND_INT_2ADDR.S */
5518/* File: armv5te/binop2addr.S */
5519    /*
5520     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5521     * that specifies an instruction that performs "result = r0 op r1".
5522     * This could be an ARM instruction or a function call.  (If the result
5523     * comes back in a register other than r0, you can override "result".)
5524     *
5525     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5526     * vCC (r1).  Useful for integer division and modulus.
5527     *
5528     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5529     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5530     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5531     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5532     */
5533    /* binop/2addr vA, vB */
5534    mov     r9, rINST, lsr #8           @ r9<- A+
5535    mov     r3, rINST, lsr #12          @ r3<- B
5536    and     r9, r9, #15
5537    GET_VREG(r1, r3)                    @ r1<- vB
5538    GET_VREG(r0, r9)                    @ r0<- vA
5539    .if 0
5540    cmp     r1, #0                      @ is second operand zero?
5541    beq     common_errDivideByZero
5542    .endif
5543    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5544
5545                               @ optional op; may set condition codes
5546    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5547    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5548    SET_VREG(r0, r9)               @ vAA<- r0
5549    GOTO_OPCODE(ip)                     @ jump to next instruction
5550    /* 10-13 instructions */
5551
5552
5553
5554/* ------------------------------ */
5555    .balign 64
5556.L_OP_OR_INT_2ADDR: /* 0xb6 */
5557/* File: armv5te/OP_OR_INT_2ADDR.S */
5558/* File: armv5te/binop2addr.S */
5559    /*
5560     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5561     * that specifies an instruction that performs "result = r0 op r1".
5562     * This could be an ARM instruction or a function call.  (If the result
5563     * comes back in a register other than r0, you can override "result".)
5564     *
5565     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5566     * vCC (r1).  Useful for integer division and modulus.
5567     *
5568     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5569     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5570     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5571     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5572     */
5573    /* binop/2addr vA, vB */
5574    mov     r9, rINST, lsr #8           @ r9<- A+
5575    mov     r3, rINST, lsr #12          @ r3<- B
5576    and     r9, r9, #15
5577    GET_VREG(r1, r3)                    @ r1<- vB
5578    GET_VREG(r0, r9)                    @ r0<- vA
5579    .if 0
5580    cmp     r1, #0                      @ is second operand zero?
5581    beq     common_errDivideByZero
5582    .endif
5583    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5584
5585                               @ optional op; may set condition codes
5586    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5587    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5588    SET_VREG(r0, r9)               @ vAA<- r0
5589    GOTO_OPCODE(ip)                     @ jump to next instruction
5590    /* 10-13 instructions */
5591
5592
5593
5594/* ------------------------------ */
5595    .balign 64
5596.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5597/* File: armv5te/OP_XOR_INT_2ADDR.S */
5598/* File: armv5te/binop2addr.S */
5599    /*
5600     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5601     * that specifies an instruction that performs "result = r0 op r1".
5602     * This could be an ARM instruction or a function call.  (If the result
5603     * comes back in a register other than r0, you can override "result".)
5604     *
5605     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5606     * vCC (r1).  Useful for integer division and modulus.
5607     *
5608     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5609     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5610     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5611     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5612     */
5613    /* binop/2addr vA, vB */
5614    mov     r9, rINST, lsr #8           @ r9<- A+
5615    mov     r3, rINST, lsr #12          @ r3<- B
5616    and     r9, r9, #15
5617    GET_VREG(r1, r3)                    @ r1<- vB
5618    GET_VREG(r0, r9)                    @ r0<- vA
5619    .if 0
5620    cmp     r1, #0                      @ is second operand zero?
5621    beq     common_errDivideByZero
5622    .endif
5623    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5624
5625                               @ optional op; may set condition codes
5626    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5627    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5628    SET_VREG(r0, r9)               @ vAA<- r0
5629    GOTO_OPCODE(ip)                     @ jump to next instruction
5630    /* 10-13 instructions */
5631
5632
5633
5634/* ------------------------------ */
5635    .balign 64
5636.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5637/* File: armv5te/OP_SHL_INT_2ADDR.S */
5638/* File: armv5te/binop2addr.S */
5639    /*
5640     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5641     * that specifies an instruction that performs "result = r0 op r1".
5642     * This could be an ARM instruction or a function call.  (If the result
5643     * comes back in a register other than r0, you can override "result".)
5644     *
5645     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5646     * vCC (r1).  Useful for integer division and modulus.
5647     *
5648     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5649     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5650     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5651     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5652     */
5653    /* binop/2addr vA, vB */
5654    mov     r9, rINST, lsr #8           @ r9<- A+
5655    mov     r3, rINST, lsr #12          @ r3<- B
5656    and     r9, r9, #15
5657    GET_VREG(r1, r3)                    @ r1<- vB
5658    GET_VREG(r0, r9)                    @ r0<- vA
5659    .if 0
5660    cmp     r1, #0                      @ is second operand zero?
5661    beq     common_errDivideByZero
5662    .endif
5663    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5664
5665    and     r1, r1, #31                           @ optional op; may set condition codes
5666    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5668    SET_VREG(r0, r9)               @ vAA<- r0
5669    GOTO_OPCODE(ip)                     @ jump to next instruction
5670    /* 10-13 instructions */
5671
5672
5673
5674/* ------------------------------ */
5675    .balign 64
5676.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5677/* File: armv5te/OP_SHR_INT_2ADDR.S */
5678/* File: armv5te/binop2addr.S */
5679    /*
5680     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5681     * that specifies an instruction that performs "result = r0 op r1".
5682     * This could be an ARM instruction or a function call.  (If the result
5683     * comes back in a register other than r0, you can override "result".)
5684     *
5685     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5686     * vCC (r1).  Useful for integer division and modulus.
5687     *
5688     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5689     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5690     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5691     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5692     */
5693    /* binop/2addr vA, vB */
5694    mov     r9, rINST, lsr #8           @ r9<- A+
5695    mov     r3, rINST, lsr #12          @ r3<- B
5696    and     r9, r9, #15
5697    GET_VREG(r1, r3)                    @ r1<- vB
5698    GET_VREG(r0, r9)                    @ r0<- vA
5699    .if 0
5700    cmp     r1, #0                      @ is second operand zero?
5701    beq     common_errDivideByZero
5702    .endif
5703    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5704
5705    and     r1, r1, #31                           @ optional op; may set condition codes
5706    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5708    SET_VREG(r0, r9)               @ vAA<- r0
5709    GOTO_OPCODE(ip)                     @ jump to next instruction
5710    /* 10-13 instructions */
5711
5712
5713
5714/* ------------------------------ */
5715    .balign 64
5716.L_OP_USHR_INT_2ADDR: /* 0xba */
5717/* File: armv5te/OP_USHR_INT_2ADDR.S */
5718/* File: armv5te/binop2addr.S */
5719    /*
5720     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5721     * that specifies an instruction that performs "result = r0 op r1".
5722     * This could be an ARM instruction or a function call.  (If the result
5723     * comes back in a register other than r0, you can override "result".)
5724     *
5725     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5726     * vCC (r1).  Useful for integer division and modulus.
5727     *
5728     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5729     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5730     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5731     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5732     */
5733    /* binop/2addr vA, vB */
5734    mov     r9, rINST, lsr #8           @ r9<- A+
5735    mov     r3, rINST, lsr #12          @ r3<- B
5736    and     r9, r9, #15
5737    GET_VREG(r1, r3)                    @ r1<- vB
5738    GET_VREG(r0, r9)                    @ r0<- vA
5739    .if 0
5740    cmp     r1, #0                      @ is second operand zero?
5741    beq     common_errDivideByZero
5742    .endif
5743    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5744
5745    and     r1, r1, #31                           @ optional op; may set condition codes
5746    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5748    SET_VREG(r0, r9)               @ vAA<- r0
5749    GOTO_OPCODE(ip)                     @ jump to next instruction
5750    /* 10-13 instructions */
5751
5752
5753
5754/* ------------------------------ */
5755    .balign 64
5756.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5757/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5758/* File: armv5te/binopWide2addr.S */
5759    /*
5760     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5761     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5762     * This could be an ARM instruction or a function call.  (If the result
5763     * comes back in a register other than r0, you can override "result".)
5764     *
5765     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5766     * vCC (r1).  Useful for integer division and modulus.
5767     *
5768     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5769     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5770     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5771     *      rem-double/2addr
5772     */
5773    /* binop/2addr vA, vB */
5774    mov     r9, rINST, lsr #8           @ r9<- A+
5775    mov     r1, rINST, lsr #12          @ r1<- B
5776    and     r9, r9, #15
5777    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5778    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5779    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5780    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5781    .if 0
5782    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5783    beq     common_errDivideByZero
5784    .endif
5785    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5786
5787    adds    r0, r0, r2                           @ optional op; may set condition codes
5788    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5790    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5791    GOTO_OPCODE(ip)                     @ jump to next instruction
5792    /* 12-15 instructions */
5793
5794
5795
5796/* ------------------------------ */
5797    .balign 64
5798.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5799/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5800/* File: armv5te/binopWide2addr.S */
5801    /*
5802     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5803     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5804     * This could be an ARM instruction or a function call.  (If the result
5805     * comes back in a register other than r0, you can override "result".)
5806     *
5807     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5808     * vCC (r1).  Useful for integer division and modulus.
5809     *
5810     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5811     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5812     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5813     *      rem-double/2addr
5814     */
5815    /* binop/2addr vA, vB */
5816    mov     r9, rINST, lsr #8           @ r9<- A+
5817    mov     r1, rINST, lsr #12          @ r1<- B
5818    and     r9, r9, #15
5819    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5820    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5821    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5822    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5823    .if 0
5824    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5825    beq     common_errDivideByZero
5826    .endif
5827    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5828
5829    subs    r0, r0, r2                           @ optional op; may set condition codes
5830    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5832    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5833    GOTO_OPCODE(ip)                     @ jump to next instruction
5834    /* 12-15 instructions */
5835
5836
5837
5838/* ------------------------------ */
5839    .balign 64
5840.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5841/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5842    /*
5843     * Signed 64-bit integer multiply, "/2addr" version.
5844     *
5845     * See OP_MUL_LONG for an explanation.
5846     *
5847     * We get a little tight on registers, so to avoid looking up &fp[A]
5848     * again we stuff it into rINST.
5849     */
5850    /* mul-long/2addr vA, vB */
5851    mov     r9, rINST, lsr #8           @ r9<- A+
5852    mov     r1, rINST, lsr #12          @ r1<- B
5853    and     r9, r9, #15
5854    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5855    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5856    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5857    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5858    mul     ip, r2, r1                  @  ip<- ZxW
5859    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5860    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5861    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5862    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5863    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5865    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5866    GOTO_OPCODE(ip)                     @ jump to next instruction
5867
5868
5869/* ------------------------------ */
5870    .balign 64
5871.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5872/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5873/* File: armv5te/binopWide2addr.S */
5874    /*
5875     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5876     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5877     * This could be an ARM instruction or a function call.  (If the result
5878     * comes back in a register other than r0, you can override "result".)
5879     *
5880     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5881     * vCC (r1).  Useful for integer division and modulus.
5882     *
5883     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5884     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5885     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5886     *      rem-double/2addr
5887     */
5888    /* binop/2addr vA, vB */
5889    mov     r9, rINST, lsr #8           @ r9<- A+
5890    mov     r1, rINST, lsr #12          @ r1<- B
5891    and     r9, r9, #15
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, {r0,r1}     @ vAA/vAA+1<- r0/r1
5906    GOTO_OPCODE(ip)                     @ jump to next instruction
5907    /* 12-15 instructions */
5908
5909
5910
5911/* ------------------------------ */
5912    .balign 64
5913.L_OP_REM_LONG_2ADDR: /* 0xbf */
5914/* File: armv5te/OP_REM_LONG_2ADDR.S */
5915/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5916/* File: armv5te/binopWide2addr.S */
5917    /*
5918     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5919     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5920     * This could be an ARM instruction or a function call.  (If the result
5921     * comes back in a register other than r0, you can override "result".)
5922     *
5923     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5924     * vCC (r1).  Useful for integer division and modulus.
5925     *
5926     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5927     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5928     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5929     *      rem-double/2addr
5930     */
5931    /* binop/2addr vA, vB */
5932    mov     r9, rINST, lsr #8           @ r9<- A+
5933    mov     r1, rINST, lsr #12          @ r1<- B
5934    and     r9, r9, #15
5935    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5936    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5937    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5938    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5939    .if 1
5940    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5941    beq     common_errDivideByZero
5942    .endif
5943    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5944
5945                               @ optional op; may set condition codes
5946    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5948    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5949    GOTO_OPCODE(ip)                     @ jump to next instruction
5950    /* 12-15 instructions */
5951
5952
5953
5954/* ------------------------------ */
5955    .balign 64
5956.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5957/* File: armv5te/OP_AND_LONG_2ADDR.S */
5958/* File: armv5te/binopWide2addr.S */
5959    /*
5960     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5961     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5962     * This could be an ARM instruction or a function call.  (If the result
5963     * comes back in a register other than r0, you can override "result".)
5964     *
5965     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5966     * vCC (r1).  Useful for integer division and modulus.
5967     *
5968     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5969     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5970     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5971     *      rem-double/2addr
5972     */
5973    /* binop/2addr vA, vB */
5974    mov     r9, rINST, lsr #8           @ r9<- A+
5975    mov     r1, rINST, lsr #12          @ r1<- B
5976    and     r9, r9, #15
5977    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5978    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5979    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5980    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5981    .if 0
5982    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5983    beq     common_errDivideByZero
5984    .endif
5985    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5986
5987    and     r0, r0, r2                           @ optional op; may set condition codes
5988    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5989    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5990    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5991    GOTO_OPCODE(ip)                     @ jump to next instruction
5992    /* 12-15 instructions */
5993
5994
5995
5996/* ------------------------------ */
5997    .balign 64
5998.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5999/* File: armv5te/OP_OR_LONG_2ADDR.S */
6000/* File: armv5te/binopWide2addr.S */
6001    /*
6002     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6003     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6004     * This could be an ARM instruction or a function call.  (If the result
6005     * comes back in a register other than r0, you can override "result".)
6006     *
6007     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6008     * vCC (r1).  Useful for integer division and modulus.
6009     *
6010     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6011     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6012     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6013     *      rem-double/2addr
6014     */
6015    /* binop/2addr vA, vB */
6016    mov     r9, rINST, lsr #8           @ r9<- A+
6017    mov     r1, rINST, lsr #12          @ r1<- B
6018    and     r9, r9, #15
6019    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6020    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6021    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6022    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6023    .if 0
6024    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6025    beq     common_errDivideByZero
6026    .endif
6027    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6028
6029    orr     r0, r0, r2                           @ optional op; may set condition codes
6030    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6031    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6032    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6033    GOTO_OPCODE(ip)                     @ jump to next instruction
6034    /* 12-15 instructions */
6035
6036
6037
6038/* ------------------------------ */
6039    .balign 64
6040.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6041/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6042/* File: armv5te/binopWide2addr.S */
6043    /*
6044     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6045     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6046     * This could be an ARM instruction or a function call.  (If the result
6047     * comes back in a register other than r0, you can override "result".)
6048     *
6049     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6050     * vCC (r1).  Useful for integer division and modulus.
6051     *
6052     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6053     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6054     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6055     *      rem-double/2addr
6056     */
6057    /* binop/2addr vA, vB */
6058    mov     r9, rINST, lsr #8           @ r9<- A+
6059    mov     r1, rINST, lsr #12          @ r1<- B
6060    and     r9, r9, #15
6061    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6062    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6063    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6064    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6065    .if 0
6066    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6067    beq     common_errDivideByZero
6068    .endif
6069    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6070
6071    eor     r0, r0, r2                           @ optional op; may set condition codes
6072    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6074    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6075    GOTO_OPCODE(ip)                     @ jump to next instruction
6076    /* 12-15 instructions */
6077
6078
6079
6080/* ------------------------------ */
6081    .balign 64
6082.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6083/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6084    /*
6085     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6086     * 32-bit shift distance.
6087     */
6088    /* shl-long/2addr vA, vB */
6089    mov     r9, rINST, lsr #8           @ r9<- A+
6090    mov     r3, rINST, lsr #12          @ r3<- B
6091    and     r9, r9, #15
6092    GET_VREG(r2, r3)                    @ r2<- vB
6093    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6094    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6095    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6096
6097    mov     r1, r1, asl r2              @  r1<- r1 << r2
6098    rsb     r3, r2, #32                 @  r3<- 32 - r2
6099    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6100    subs    ip, r2, #32                 @  ip<- r2 - 32
6101    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6102    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6103    mov     r0, r0, asl r2              @  r0<- r0 << r2
6104    b       .LOP_SHL_LONG_2ADDR_finish
6105
6106/* ------------------------------ */
6107    .balign 64
6108.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6109/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6110    /*
6111     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6112     * 32-bit shift distance.
6113     */
6114    /* shr-long/2addr vA, vB */
6115    mov     r9, rINST, lsr #8           @ r9<- A+
6116    mov     r3, rINST, lsr #12          @ r3<- B
6117    and     r9, r9, #15
6118    GET_VREG(r2, r3)                    @ r2<- vB
6119    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6120    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6121    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6122
6123    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6124    rsb     r3, r2, #32                 @  r3<- 32 - r2
6125    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6126    subs    ip, r2, #32                 @  ip<- r2 - 32
6127    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6128    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6129    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6130    b       .LOP_SHR_LONG_2ADDR_finish
6131
6132/* ------------------------------ */
6133    .balign 64
6134.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6135/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6136    /*
6137     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6138     * 32-bit shift distance.
6139     */
6140    /* ushr-long/2addr vA, vB */
6141    mov     r9, rINST, lsr #8           @ r9<- A+
6142    mov     r3, rINST, lsr #12          @ r3<- B
6143    and     r9, r9, #15
6144    GET_VREG(r2, r3)                    @ r2<- vB
6145    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6146    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6147    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6148
6149    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6150    rsb     r3, r2, #32                 @  r3<- 32 - r2
6151    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6152    subs    ip, r2, #32                 @  ip<- r2 - 32
6153    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6154    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6155    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6156    b       .LOP_USHR_LONG_2ADDR_finish
6157
6158/* ------------------------------ */
6159    .balign 64
6160.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6161/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6162/* File: arm-vfp/fbinop2addr.S */
6163    /*
6164     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6165     * an "instr" line that specifies an instruction that performs
6166     * "s2 = s0 op s1".
6167     *
6168     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6169     */
6170    /* binop/2addr vA, vB */
6171    mov     r3, rINST, lsr #12          @ r3<- B
6172    mov     r9, rINST, lsr #8           @ r9<- A+
6173    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6174    and     r9, r9, #15                 @ r9<- A
6175    flds    s1, [r3]                    @ s1<- vB
6176    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6177    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6178    flds    s0, [r9]                    @ s0<- vA
6179
6180    fadds   s2, s0, s1                              @ s2<- op
6181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6182    fsts    s2, [r9]                    @ vAA<- s2
6183    GOTO_OPCODE(ip)                     @ jump to next instruction
6184
6185
6186/* ------------------------------ */
6187    .balign 64
6188.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6189/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6190/* File: arm-vfp/fbinop2addr.S */
6191    /*
6192     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6193     * an "instr" line that specifies an instruction that performs
6194     * "s2 = s0 op s1".
6195     *
6196     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6197     */
6198    /* binop/2addr vA, vB */
6199    mov     r3, rINST, lsr #12          @ r3<- B
6200    mov     r9, rINST, lsr #8           @ r9<- A+
6201    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6202    and     r9, r9, #15                 @ r9<- A
6203    flds    s1, [r3]                    @ s1<- vB
6204    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6205    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6206    flds    s0, [r9]                    @ s0<- vA
6207
6208    fsubs   s2, s0, s1                              @ s2<- op
6209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6210    fsts    s2, [r9]                    @ vAA<- s2
6211    GOTO_OPCODE(ip)                     @ jump to next instruction
6212
6213
6214/* ------------------------------ */
6215    .balign 64
6216.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6217/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6218/* File: arm-vfp/fbinop2addr.S */
6219    /*
6220     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6221     * an "instr" line that specifies an instruction that performs
6222     * "s2 = s0 op s1".
6223     *
6224     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6225     */
6226    /* binop/2addr vA, vB */
6227    mov     r3, rINST, lsr #12          @ r3<- B
6228    mov     r9, rINST, lsr #8           @ r9<- A+
6229    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6230    and     r9, r9, #15                 @ r9<- A
6231    flds    s1, [r3]                    @ s1<- vB
6232    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6233    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6234    flds    s0, [r9]                    @ s0<- vA
6235
6236    fmuls   s2, s0, s1                              @ s2<- op
6237    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6238    fsts    s2, [r9]                    @ vAA<- s2
6239    GOTO_OPCODE(ip)                     @ jump to next instruction
6240
6241
6242/* ------------------------------ */
6243    .balign 64
6244.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6245/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6246/* File: arm-vfp/fbinop2addr.S */
6247    /*
6248     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6249     * an "instr" line that specifies an instruction that performs
6250     * "s2 = s0 op s1".
6251     *
6252     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6253     */
6254    /* binop/2addr vA, vB */
6255    mov     r3, rINST, lsr #12          @ r3<- B
6256    mov     r9, rINST, lsr #8           @ r9<- A+
6257    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6258    and     r9, r9, #15                 @ r9<- A
6259    flds    s1, [r3]                    @ s1<- vB
6260    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6261    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6262    flds    s0, [r9]                    @ s0<- vA
6263
6264    fdivs   s2, s0, s1                              @ s2<- op
6265    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6266    fsts    s2, [r9]                    @ vAA<- s2
6267    GOTO_OPCODE(ip)                     @ jump to next instruction
6268
6269
6270/* ------------------------------ */
6271    .balign 64
6272.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6273/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6274/* EABI doesn't define a float remainder function, but libm does */
6275/* File: armv5te/binop2addr.S */
6276    /*
6277     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6278     * that specifies an instruction that performs "result = r0 op r1".
6279     * This could be an ARM instruction or a function call.  (If the result
6280     * comes back in a register other than r0, you can override "result".)
6281     *
6282     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6283     * vCC (r1).  Useful for integer division and modulus.
6284     *
6285     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6286     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6287     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6288     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6289     */
6290    /* binop/2addr vA, vB */
6291    mov     r9, rINST, lsr #8           @ r9<- A+
6292    mov     r3, rINST, lsr #12          @ r3<- B
6293    and     r9, r9, #15
6294    GET_VREG(r1, r3)                    @ r1<- vB
6295    GET_VREG(r0, r9)                    @ r0<- vA
6296    .if 0
6297    cmp     r1, #0                      @ is second operand zero?
6298    beq     common_errDivideByZero
6299    .endif
6300    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6301
6302                               @ optional op; may set condition codes
6303    bl      fmodf                              @ r0<- op, r0-r3 changed
6304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6305    SET_VREG(r0, r9)               @ vAA<- r0
6306    GOTO_OPCODE(ip)                     @ jump to next instruction
6307    /* 10-13 instructions */
6308
6309
6310
6311/* ------------------------------ */
6312    .balign 64
6313.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6314/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6315/* File: arm-vfp/fbinopWide2addr.S */
6316    /*
6317     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6318     * an "instr" line that specifies an instruction that performs
6319     * "d2 = d0 op d1".
6320     *
6321     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6322     *      div-double/2addr
6323     */
6324    /* binop/2addr vA, vB */
6325    mov     r3, rINST, lsr #12          @ r3<- B
6326    mov     r9, rINST, lsr #8           @ r9<- A+
6327    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6328    and     r9, r9, #15                 @ r9<- A
6329    fldd    d1, [r3]                    @ d1<- vB
6330    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6331    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6332    fldd    d0, [r9]                    @ d0<- vA
6333
6334    faddd   d2, d0, d1                              @ d2<- op
6335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6336    fstd    d2, [r9]                    @ vAA<- d2
6337    GOTO_OPCODE(ip)                     @ jump to next instruction
6338
6339
6340/* ------------------------------ */
6341    .balign 64
6342.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6343/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6344/* File: arm-vfp/fbinopWide2addr.S */
6345    /*
6346     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6347     * an "instr" line that specifies an instruction that performs
6348     * "d2 = d0 op d1".
6349     *
6350     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6351     *      div-double/2addr
6352     */
6353    /* binop/2addr vA, vB */
6354    mov     r3, rINST, lsr #12          @ r3<- B
6355    mov     r9, rINST, lsr #8           @ r9<- A+
6356    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6357    and     r9, r9, #15                 @ r9<- A
6358    fldd    d1, [r3]                    @ d1<- vB
6359    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6360    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6361    fldd    d0, [r9]                    @ d0<- vA
6362
6363    fsubd   d2, d0, d1                              @ d2<- op
6364    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6365    fstd    d2, [r9]                    @ vAA<- d2
6366    GOTO_OPCODE(ip)                     @ jump to next instruction
6367
6368
6369/* ------------------------------ */
6370    .balign 64
6371.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6372/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6373/* File: arm-vfp/fbinopWide2addr.S */
6374    /*
6375     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6376     * an "instr" line that specifies an instruction that performs
6377     * "d2 = d0 op d1".
6378     *
6379     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6380     *      div-double/2addr
6381     */
6382    /* binop/2addr vA, vB */
6383    mov     r3, rINST, lsr #12          @ r3<- B
6384    mov     r9, rINST, lsr #8           @ r9<- A+
6385    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6386    and     r9, r9, #15                 @ r9<- A
6387    fldd    d1, [r3]                    @ d1<- vB
6388    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6389    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6390    fldd    d0, [r9]                    @ d0<- vA
6391
6392    fmuld   d2, d0, d1                              @ d2<- op
6393    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6394    fstd    d2, [r9]                    @ vAA<- d2
6395    GOTO_OPCODE(ip)                     @ jump to next instruction
6396
6397
6398/* ------------------------------ */
6399    .balign 64
6400.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6401/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6402/* File: arm-vfp/fbinopWide2addr.S */
6403    /*
6404     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6405     * an "instr" line that specifies an instruction that performs
6406     * "d2 = d0 op d1".
6407     *
6408     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6409     *      div-double/2addr
6410     */
6411    /* binop/2addr vA, vB */
6412    mov     r3, rINST, lsr #12          @ r3<- B
6413    mov     r9, rINST, lsr #8           @ r9<- A+
6414    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6415    and     r9, r9, #15                 @ r9<- A
6416    fldd    d1, [r3]                    @ d1<- vB
6417    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6418    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6419    fldd    d0, [r9]                    @ d0<- vA
6420
6421    fdivd   d2, d0, d1                              @ d2<- op
6422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6423    fstd    d2, [r9]                    @ vAA<- d2
6424    GOTO_OPCODE(ip)                     @ jump to next instruction
6425
6426
6427/* ------------------------------ */
6428    .balign 64
6429.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6430/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6431/* EABI doesn't define a double remainder function, but libm does */
6432/* File: armv5te/binopWide2addr.S */
6433    /*
6434     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6435     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6436     * This could be an ARM instruction or a function call.  (If the result
6437     * comes back in a register other than r0, you can override "result".)
6438     *
6439     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6440     * vCC (r1).  Useful for integer division and modulus.
6441     *
6442     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6443     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6444     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6445     *      rem-double/2addr
6446     */
6447    /* binop/2addr vA, vB */
6448    mov     r9, rINST, lsr #8           @ r9<- A+
6449    mov     r1, rINST, lsr #12          @ r1<- B
6450    and     r9, r9, #15
6451    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6452    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6453    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6454    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6455    .if 0
6456    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6457    beq     common_errDivideByZero
6458    .endif
6459    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6460
6461                               @ optional op; may set condition codes
6462    bl      fmod                              @ result<- op, r0-r3 changed
6463    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6464    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6465    GOTO_OPCODE(ip)                     @ jump to next instruction
6466    /* 12-15 instructions */
6467
6468
6469
6470/* ------------------------------ */
6471    .balign 64
6472.L_OP_ADD_INT_LIT16: /* 0xd0 */
6473/* File: armv5te/OP_ADD_INT_LIT16.S */
6474/* File: armv5te/binopLit16.S */
6475    /*
6476     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6477     * that specifies an instruction that performs "result = r0 op r1".
6478     * This could be an ARM instruction or a function call.  (If the result
6479     * comes back in a register other than r0, you can override "result".)
6480     *
6481     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6482     * vCC (r1).  Useful for integer division and modulus.
6483     *
6484     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6485     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6486     */
6487    /* binop/lit16 vA, vB, #+CCCC */
6488    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6489    mov     r2, rINST, lsr #12          @ r2<- B
6490    mov     r9, rINST, lsr #8           @ r9<- A+
6491    GET_VREG(r0, r2)                    @ r0<- vB
6492    and     r9, r9, #15
6493    .if 0
6494    cmp     r1, #0                      @ is second operand zero?
6495    beq     common_errDivideByZero
6496    .endif
6497    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6498
6499    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6500    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6501    SET_VREG(r0, r9)               @ vAA<- r0
6502    GOTO_OPCODE(ip)                     @ jump to next instruction
6503    /* 10-13 instructions */
6504
6505
6506
6507/* ------------------------------ */
6508    .balign 64
6509.L_OP_RSUB_INT: /* 0xd1 */
6510/* File: armv5te/OP_RSUB_INT.S */
6511/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6512/* File: armv5te/binopLit16.S */
6513    /*
6514     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6515     * that specifies an instruction that performs "result = r0 op r1".
6516     * This could be an ARM instruction or a function call.  (If the result
6517     * comes back in a register other than r0, you can override "result".)
6518     *
6519     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6520     * vCC (r1).  Useful for integer division and modulus.
6521     *
6522     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6523     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6524     */
6525    /* binop/lit16 vA, vB, #+CCCC */
6526    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6527    mov     r2, rINST, lsr #12          @ r2<- B
6528    mov     r9, rINST, lsr #8           @ r9<- A+
6529    GET_VREG(r0, r2)                    @ r0<- vB
6530    and     r9, r9, #15
6531    .if 0
6532    cmp     r1, #0                      @ is second operand zero?
6533    beq     common_errDivideByZero
6534    .endif
6535    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6536
6537    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6538    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6539    SET_VREG(r0, r9)               @ vAA<- r0
6540    GOTO_OPCODE(ip)                     @ jump to next instruction
6541    /* 10-13 instructions */
6542
6543
6544
6545/* ------------------------------ */
6546    .balign 64
6547.L_OP_MUL_INT_LIT16: /* 0xd2 */
6548/* File: armv5te/OP_MUL_INT_LIT16.S */
6549/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6550/* File: armv5te/binopLit16.S */
6551    /*
6552     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6553     * that specifies an instruction that performs "result = r0 op r1".
6554     * This could be an ARM instruction or a function call.  (If the result
6555     * comes back in a register other than r0, you can override "result".)
6556     *
6557     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6558     * vCC (r1).  Useful for integer division and modulus.
6559     *
6560     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6561     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6562     */
6563    /* binop/lit16 vA, vB, #+CCCC */
6564    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6565    mov     r2, rINST, lsr #12          @ r2<- B
6566    mov     r9, rINST, lsr #8           @ r9<- A+
6567    GET_VREG(r0, r2)                    @ r0<- vB
6568    and     r9, r9, #15
6569    .if 0
6570    cmp     r1, #0                      @ is second operand zero?
6571    beq     common_errDivideByZero
6572    .endif
6573    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6574
6575    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6577    SET_VREG(r0, r9)               @ vAA<- r0
6578    GOTO_OPCODE(ip)                     @ jump to next instruction
6579    /* 10-13 instructions */
6580
6581
6582
6583/* ------------------------------ */
6584    .balign 64
6585.L_OP_DIV_INT_LIT16: /* 0xd3 */
6586/* File: armv5te/OP_DIV_INT_LIT16.S */
6587/* File: armv5te/binopLit16.S */
6588    /*
6589     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6590     * that specifies an instruction that performs "result = r0 op r1".
6591     * This could be an ARM instruction or a function call.  (If the result
6592     * comes back in a register other than r0, you can override "result".)
6593     *
6594     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6595     * vCC (r1).  Useful for integer division and modulus.
6596     *
6597     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6598     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6599     */
6600    /* binop/lit16 vA, vB, #+CCCC */
6601    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6602    mov     r2, rINST, lsr #12          @ r2<- B
6603    mov     r9, rINST, lsr #8           @ r9<- A+
6604    GET_VREG(r0, r2)                    @ r0<- vB
6605    and     r9, r9, #15
6606    .if 1
6607    cmp     r1, #0                      @ is second operand zero?
6608    beq     common_errDivideByZero
6609    .endif
6610    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6611
6612    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6614    SET_VREG(r0, r9)               @ vAA<- r0
6615    GOTO_OPCODE(ip)                     @ jump to next instruction
6616    /* 10-13 instructions */
6617
6618
6619
6620/* ------------------------------ */
6621    .balign 64
6622.L_OP_REM_INT_LIT16: /* 0xd4 */
6623/* File: armv5te/OP_REM_INT_LIT16.S */
6624/* idivmod returns quotient in r0 and remainder in r1 */
6625/* File: armv5te/binopLit16.S */
6626    /*
6627     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6628     * that specifies an instruction that performs "result = r0 op r1".
6629     * This could be an ARM instruction or a function call.  (If the result
6630     * comes back in a register other than r0, you can override "result".)
6631     *
6632     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6633     * vCC (r1).  Useful for integer division and modulus.
6634     *
6635     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6636     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6637     */
6638    /* binop/lit16 vA, vB, #+CCCC */
6639    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6640    mov     r2, rINST, lsr #12          @ r2<- B
6641    mov     r9, rINST, lsr #8           @ r9<- A+
6642    GET_VREG(r0, r2)                    @ r0<- vB
6643    and     r9, r9, #15
6644    .if 1
6645    cmp     r1, #0                      @ is second operand zero?
6646    beq     common_errDivideByZero
6647    .endif
6648    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6649
6650    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6651    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6652    SET_VREG(r1, r9)               @ vAA<- r1
6653    GOTO_OPCODE(ip)                     @ jump to next instruction
6654    /* 10-13 instructions */
6655
6656
6657
6658/* ------------------------------ */
6659    .balign 64
6660.L_OP_AND_INT_LIT16: /* 0xd5 */
6661/* File: armv5te/OP_AND_INT_LIT16.S */
6662/* File: armv5te/binopLit16.S */
6663    /*
6664     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6665     * that specifies an instruction that performs "result = r0 op r1".
6666     * This could be an ARM instruction or a function call.  (If the result
6667     * comes back in a register other than r0, you can override "result".)
6668     *
6669     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6670     * vCC (r1).  Useful for integer division and modulus.
6671     *
6672     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6673     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6674     */
6675    /* binop/lit16 vA, vB, #+CCCC */
6676    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6677    mov     r2, rINST, lsr #12          @ r2<- B
6678    mov     r9, rINST, lsr #8           @ r9<- A+
6679    GET_VREG(r0, r2)                    @ r0<- vB
6680    and     r9, r9, #15
6681    .if 0
6682    cmp     r1, #0                      @ is second operand zero?
6683    beq     common_errDivideByZero
6684    .endif
6685    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6686
6687    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6689    SET_VREG(r0, r9)               @ vAA<- r0
6690    GOTO_OPCODE(ip)                     @ jump to next instruction
6691    /* 10-13 instructions */
6692
6693
6694
6695/* ------------------------------ */
6696    .balign 64
6697.L_OP_OR_INT_LIT16: /* 0xd6 */
6698/* File: armv5te/OP_OR_INT_LIT16.S */
6699/* File: armv5te/binopLit16.S */
6700    /*
6701     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6702     * that specifies an instruction that performs "result = r0 op r1".
6703     * This could be an ARM instruction or a function call.  (If the result
6704     * comes back in a register other than r0, you can override "result".)
6705     *
6706     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6707     * vCC (r1).  Useful for integer division and modulus.
6708     *
6709     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6710     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6711     */
6712    /* binop/lit16 vA, vB, #+CCCC */
6713    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6714    mov     r2, rINST, lsr #12          @ r2<- B
6715    mov     r9, rINST, lsr #8           @ r9<- A+
6716    GET_VREG(r0, r2)                    @ r0<- vB
6717    and     r9, r9, #15
6718    .if 0
6719    cmp     r1, #0                      @ is second operand zero?
6720    beq     common_errDivideByZero
6721    .endif
6722    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6723
6724    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6726    SET_VREG(r0, r9)               @ vAA<- r0
6727    GOTO_OPCODE(ip)                     @ jump to next instruction
6728    /* 10-13 instructions */
6729
6730
6731
6732/* ------------------------------ */
6733    .balign 64
6734.L_OP_XOR_INT_LIT16: /* 0xd7 */
6735/* File: armv5te/OP_XOR_INT_LIT16.S */
6736/* File: armv5te/binopLit16.S */
6737    /*
6738     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6739     * that specifies an instruction that performs "result = r0 op r1".
6740     * This could be an ARM instruction or a function call.  (If the result
6741     * comes back in a register other than r0, you can override "result".)
6742     *
6743     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6744     * vCC (r1).  Useful for integer division and modulus.
6745     *
6746     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6747     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6748     */
6749    /* binop/lit16 vA, vB, #+CCCC */
6750    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6751    mov     r2, rINST, lsr #12          @ r2<- B
6752    mov     r9, rINST, lsr #8           @ r9<- A+
6753    GET_VREG(r0, r2)                    @ r0<- vB
6754    and     r9, r9, #15
6755    .if 0
6756    cmp     r1, #0                      @ is second operand zero?
6757    beq     common_errDivideByZero
6758    .endif
6759    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6760
6761    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6763    SET_VREG(r0, r9)               @ vAA<- r0
6764    GOTO_OPCODE(ip)                     @ jump to next instruction
6765    /* 10-13 instructions */
6766
6767
6768
6769/* ------------------------------ */
6770    .balign 64
6771.L_OP_ADD_INT_LIT8: /* 0xd8 */
6772/* File: armv5te/OP_ADD_INT_LIT8.S */
6773/* File: armv5te/binopLit8.S */
6774    /*
6775     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6776     * that specifies an instruction that performs "result = r0 op r1".
6777     * This could be an ARM instruction or a function call.  (If the result
6778     * comes back in a register other than r0, you can override "result".)
6779     *
6780     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6781     * vCC (r1).  Useful for integer division and modulus.
6782     *
6783     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6784     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6785     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6786     */
6787    /* binop/lit8 vAA, vBB, #+CC */
6788    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6789    mov     r9, rINST, lsr #8           @ r9<- AA
6790    and     r2, r3, #255                @ r2<- BB
6791    GET_VREG(r0, r2)                    @ r0<- vBB
6792    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6793    .if 0
6794    @cmp     r1, #0                      @ is second operand zero?
6795    beq     common_errDivideByZero
6796    .endif
6797    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6798
6799                               @ optional op; may set condition codes
6800    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6802    SET_VREG(r0, r9)               @ vAA<- r0
6803    GOTO_OPCODE(ip)                     @ jump to next instruction
6804    /* 10-12 instructions */
6805
6806
6807
6808/* ------------------------------ */
6809    .balign 64
6810.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6811/* File: armv5te/OP_RSUB_INT_LIT8.S */
6812/* File: armv5te/binopLit8.S */
6813    /*
6814     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6815     * that specifies an instruction that performs "result = r0 op r1".
6816     * This could be an ARM instruction or a function call.  (If the result
6817     * comes back in a register other than r0, you can override "result".)
6818     *
6819     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6820     * vCC (r1).  Useful for integer division and modulus.
6821     *
6822     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6823     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6824     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6825     */
6826    /* binop/lit8 vAA, vBB, #+CC */
6827    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6828    mov     r9, rINST, lsr #8           @ r9<- AA
6829    and     r2, r3, #255                @ r2<- BB
6830    GET_VREG(r0, r2)                    @ r0<- vBB
6831    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6832    .if 0
6833    @cmp     r1, #0                      @ is second operand zero?
6834    beq     common_errDivideByZero
6835    .endif
6836    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6837
6838                               @ optional op; may set condition codes
6839    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6841    SET_VREG(r0, r9)               @ vAA<- r0
6842    GOTO_OPCODE(ip)                     @ jump to next instruction
6843    /* 10-12 instructions */
6844
6845
6846
6847/* ------------------------------ */
6848    .balign 64
6849.L_OP_MUL_INT_LIT8: /* 0xda */
6850/* File: armv5te/OP_MUL_INT_LIT8.S */
6851/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6852/* File: armv5te/binopLit8.S */
6853    /*
6854     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6855     * that specifies an instruction that performs "result = r0 op r1".
6856     * This could be an ARM instruction or a function call.  (If the result
6857     * comes back in a register other than r0, you can override "result".)
6858     *
6859     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6860     * vCC (r1).  Useful for integer division and modulus.
6861     *
6862     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6863     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6864     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6865     */
6866    /* binop/lit8 vAA, vBB, #+CC */
6867    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6868    mov     r9, rINST, lsr #8           @ r9<- AA
6869    and     r2, r3, #255                @ r2<- BB
6870    GET_VREG(r0, r2)                    @ r0<- vBB
6871    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6872    .if 0
6873    @cmp     r1, #0                      @ is second operand zero?
6874    beq     common_errDivideByZero
6875    .endif
6876    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6877
6878                               @ optional op; may set condition codes
6879    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6880    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6881    SET_VREG(r0, r9)               @ vAA<- r0
6882    GOTO_OPCODE(ip)                     @ jump to next instruction
6883    /* 10-12 instructions */
6884
6885
6886
6887/* ------------------------------ */
6888    .balign 64
6889.L_OP_DIV_INT_LIT8: /* 0xdb */
6890/* File: armv5te/OP_DIV_INT_LIT8.S */
6891/* File: armv5te/binopLit8.S */
6892    /*
6893     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6894     * that specifies an instruction that performs "result = r0 op r1".
6895     * This could be an ARM instruction or a function call.  (If the result
6896     * comes back in a register other than r0, you can override "result".)
6897     *
6898     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6899     * vCC (r1).  Useful for integer division and modulus.
6900     *
6901     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6902     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6903     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6904     */
6905    /* binop/lit8 vAA, vBB, #+CC */
6906    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6907    mov     r9, rINST, lsr #8           @ r9<- AA
6908    and     r2, r3, #255                @ r2<- BB
6909    GET_VREG(r0, r2)                    @ r0<- vBB
6910    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6911    .if 1
6912    @cmp     r1, #0                      @ is second operand zero?
6913    beq     common_errDivideByZero
6914    .endif
6915    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6916
6917                               @ optional op; may set condition codes
6918    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6920    SET_VREG(r0, r9)               @ vAA<- r0
6921    GOTO_OPCODE(ip)                     @ jump to next instruction
6922    /* 10-12 instructions */
6923
6924
6925
6926/* ------------------------------ */
6927    .balign 64
6928.L_OP_REM_INT_LIT8: /* 0xdc */
6929/* File: armv5te/OP_REM_INT_LIT8.S */
6930/* idivmod returns quotient in r0 and remainder in r1 */
6931/* File: armv5te/binopLit8.S */
6932    /*
6933     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6934     * that specifies an instruction that performs "result = r0 op r1".
6935     * This could be an ARM instruction or a function call.  (If the result
6936     * comes back in a register other than r0, you can override "result".)
6937     *
6938     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6939     * vCC (r1).  Useful for integer division and modulus.
6940     *
6941     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6942     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6943     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6944     */
6945    /* binop/lit8 vAA, vBB, #+CC */
6946    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6947    mov     r9, rINST, lsr #8           @ r9<- AA
6948    and     r2, r3, #255                @ r2<- BB
6949    GET_VREG(r0, r2)                    @ r0<- vBB
6950    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6951    .if 1
6952    @cmp     r1, #0                      @ is second operand zero?
6953    beq     common_errDivideByZero
6954    .endif
6955    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6956
6957                               @ optional op; may set condition codes
6958    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6959    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6960    SET_VREG(r1, r9)               @ vAA<- r1
6961    GOTO_OPCODE(ip)                     @ jump to next instruction
6962    /* 10-12 instructions */
6963
6964
6965
6966/* ------------------------------ */
6967    .balign 64
6968.L_OP_AND_INT_LIT8: /* 0xdd */
6969/* File: armv5te/OP_AND_INT_LIT8.S */
6970/* File: armv5te/binopLit8.S */
6971    /*
6972     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6973     * that specifies an instruction that performs "result = r0 op r1".
6974     * This could be an ARM instruction or a function call.  (If the result
6975     * comes back in a register other than r0, you can override "result".)
6976     *
6977     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6978     * vCC (r1).  Useful for integer division and modulus.
6979     *
6980     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6981     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6982     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6983     */
6984    /* binop/lit8 vAA, vBB, #+CC */
6985    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6986    mov     r9, rINST, lsr #8           @ r9<- AA
6987    and     r2, r3, #255                @ r2<- BB
6988    GET_VREG(r0, r2)                    @ r0<- vBB
6989    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6990    .if 0
6991    @cmp     r1, #0                      @ is second operand zero?
6992    beq     common_errDivideByZero
6993    .endif
6994    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6995
6996                               @ optional op; may set condition codes
6997    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6999    SET_VREG(r0, r9)               @ vAA<- r0
7000    GOTO_OPCODE(ip)                     @ jump to next instruction
7001    /* 10-12 instructions */
7002
7003
7004
7005/* ------------------------------ */
7006    .balign 64
7007.L_OP_OR_INT_LIT8: /* 0xde */
7008/* File: armv5te/OP_OR_INT_LIT8.S */
7009/* File: armv5te/binopLit8.S */
7010    /*
7011     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7012     * that specifies an instruction that performs "result = r0 op r1".
7013     * This could be an ARM instruction or a function call.  (If the result
7014     * comes back in a register other than r0, you can override "result".)
7015     *
7016     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7017     * vCC (r1).  Useful for integer division and modulus.
7018     *
7019     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7020     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7021     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7022     */
7023    /* binop/lit8 vAA, vBB, #+CC */
7024    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7025    mov     r9, rINST, lsr #8           @ r9<- AA
7026    and     r2, r3, #255                @ r2<- BB
7027    GET_VREG(r0, r2)                    @ r0<- vBB
7028    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7029    .if 0
7030    @cmp     r1, #0                      @ is second operand zero?
7031    beq     common_errDivideByZero
7032    .endif
7033    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7034
7035                               @ optional op; may set condition codes
7036    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7037    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7038    SET_VREG(r0, r9)               @ vAA<- r0
7039    GOTO_OPCODE(ip)                     @ jump to next instruction
7040    /* 10-12 instructions */
7041
7042
7043
7044/* ------------------------------ */
7045    .balign 64
7046.L_OP_XOR_INT_LIT8: /* 0xdf */
7047/* File: armv5te/OP_XOR_INT_LIT8.S */
7048/* File: armv5te/binopLit8.S */
7049    /*
7050     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7051     * that specifies an instruction that performs "result = r0 op r1".
7052     * This could be an ARM instruction or a function call.  (If the result
7053     * comes back in a register other than r0, you can override "result".)
7054     *
7055     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7056     * vCC (r1).  Useful for integer division and modulus.
7057     *
7058     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7059     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7060     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7061     */
7062    /* binop/lit8 vAA, vBB, #+CC */
7063    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7064    mov     r9, rINST, lsr #8           @ r9<- AA
7065    and     r2, r3, #255                @ r2<- BB
7066    GET_VREG(r0, r2)                    @ r0<- vBB
7067    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7068    .if 0
7069    @cmp     r1, #0                      @ is second operand zero?
7070    beq     common_errDivideByZero
7071    .endif
7072    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7073
7074                               @ optional op; may set condition codes
7075    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7076    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7077    SET_VREG(r0, r9)               @ vAA<- r0
7078    GOTO_OPCODE(ip)                     @ jump to next instruction
7079    /* 10-12 instructions */
7080
7081
7082
7083/* ------------------------------ */
7084    .balign 64
7085.L_OP_SHL_INT_LIT8: /* 0xe0 */
7086/* File: armv5te/OP_SHL_INT_LIT8.S */
7087/* File: armv5te/binopLit8.S */
7088    /*
7089     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7090     * that specifies an instruction that performs "result = r0 op r1".
7091     * This could be an ARM instruction or a function call.  (If the result
7092     * comes back in a register other than r0, you can override "result".)
7093     *
7094     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7095     * vCC (r1).  Useful for integer division and modulus.
7096     *
7097     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7098     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7099     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7100     */
7101    /* binop/lit8 vAA, vBB, #+CC */
7102    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7103    mov     r9, rINST, lsr #8           @ r9<- AA
7104    and     r2, r3, #255                @ r2<- BB
7105    GET_VREG(r0, r2)                    @ r0<- vBB
7106    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7107    .if 0
7108    @cmp     r1, #0                      @ is second operand zero?
7109    beq     common_errDivideByZero
7110    .endif
7111    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7112
7113    and     r1, r1, #31                           @ optional op; may set condition codes
7114    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7116    SET_VREG(r0, r9)               @ vAA<- r0
7117    GOTO_OPCODE(ip)                     @ jump to next instruction
7118    /* 10-12 instructions */
7119
7120
7121
7122/* ------------------------------ */
7123    .balign 64
7124.L_OP_SHR_INT_LIT8: /* 0xe1 */
7125/* File: armv5te/OP_SHR_INT_LIT8.S */
7126/* File: armv5te/binopLit8.S */
7127    /*
7128     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7129     * that specifies an instruction that performs "result = r0 op r1".
7130     * This could be an ARM instruction or a function call.  (If the result
7131     * comes back in a register other than r0, you can override "result".)
7132     *
7133     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7134     * vCC (r1).  Useful for integer division and modulus.
7135     *
7136     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7137     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7138     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7139     */
7140    /* binop/lit8 vAA, vBB, #+CC */
7141    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7142    mov     r9, rINST, lsr #8           @ r9<- AA
7143    and     r2, r3, #255                @ r2<- BB
7144    GET_VREG(r0, r2)                    @ r0<- vBB
7145    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7146    .if 0
7147    @cmp     r1, #0                      @ is second operand zero?
7148    beq     common_errDivideByZero
7149    .endif
7150    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7151
7152    and     r1, r1, #31                           @ optional op; may set condition codes
7153    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7155    SET_VREG(r0, r9)               @ vAA<- r0
7156    GOTO_OPCODE(ip)                     @ jump to next instruction
7157    /* 10-12 instructions */
7158
7159
7160
7161/* ------------------------------ */
7162    .balign 64
7163.L_OP_USHR_INT_LIT8: /* 0xe2 */
7164/* File: armv5te/OP_USHR_INT_LIT8.S */
7165/* File: armv5te/binopLit8.S */
7166    /*
7167     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7168     * that specifies an instruction that performs "result = r0 op r1".
7169     * This could be an ARM instruction or a function call.  (If the result
7170     * comes back in a register other than r0, you can override "result".)
7171     *
7172     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7173     * vCC (r1).  Useful for integer division and modulus.
7174     *
7175     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7176     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7177     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7178     */
7179    /* binop/lit8 vAA, vBB, #+CC */
7180    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7181    mov     r9, rINST, lsr #8           @ r9<- AA
7182    and     r2, r3, #255                @ r2<- BB
7183    GET_VREG(r0, r2)                    @ r0<- vBB
7184    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7185    .if 0
7186    @cmp     r1, #0                      @ is second operand zero?
7187    beq     common_errDivideByZero
7188    .endif
7189    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7190
7191    and     r1, r1, #31                           @ optional op; may set condition codes
7192    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7194    SET_VREG(r0, r9)               @ vAA<- r0
7195    GOTO_OPCODE(ip)                     @ jump to next instruction
7196    /* 10-12 instructions */
7197
7198
7199
7200/* ------------------------------ */
7201    .balign 64
7202.L_OP_UNUSED_E3: /* 0xe3 */
7203/* File: armv5te/OP_UNUSED_E3.S */
7204/* File: armv5te/unused.S */
7205    bl      common_abort
7206
7207
7208
7209/* ------------------------------ */
7210    .balign 64
7211.L_OP_UNUSED_E4: /* 0xe4 */
7212/* File: armv5te/OP_UNUSED_E4.S */
7213/* File: armv5te/unused.S */
7214    bl      common_abort
7215
7216
7217
7218/* ------------------------------ */
7219    .balign 64
7220.L_OP_UNUSED_E5: /* 0xe5 */
7221/* File: armv5te/OP_UNUSED_E5.S */
7222/* File: armv5te/unused.S */
7223    bl      common_abort
7224
7225
7226
7227/* ------------------------------ */
7228    .balign 64
7229.L_OP_UNUSED_E6: /* 0xe6 */
7230/* File: armv5te/OP_UNUSED_E6.S */
7231/* File: armv5te/unused.S */
7232    bl      common_abort
7233
7234
7235
7236/* ------------------------------ */
7237    .balign 64
7238.L_OP_UNUSED_E7: /* 0xe7 */
7239/* File: armv5te/OP_UNUSED_E7.S */
7240/* File: armv5te/unused.S */
7241    bl      common_abort
7242
7243
7244
7245/* ------------------------------ */
7246    .balign 64
7247.L_OP_UNUSED_E8: /* 0xe8 */
7248/* File: armv5te/OP_UNUSED_E8.S */
7249/* File: armv5te/unused.S */
7250    bl      common_abort
7251
7252
7253
7254/* ------------------------------ */
7255    .balign 64
7256.L_OP_UNUSED_E9: /* 0xe9 */
7257/* File: armv5te/OP_UNUSED_E9.S */
7258/* File: armv5te/unused.S */
7259    bl      common_abort
7260
7261
7262
7263/* ------------------------------ */
7264    .balign 64
7265.L_OP_UNUSED_EA: /* 0xea */
7266/* File: armv5te/OP_UNUSED_EA.S */
7267/* File: armv5te/unused.S */
7268    bl      common_abort
7269
7270
7271
7272/* ------------------------------ */
7273    .balign 64
7274.L_OP_UNUSED_EB: /* 0xeb */
7275/* File: armv5te/OP_UNUSED_EB.S */
7276/* File: armv5te/unused.S */
7277    bl      common_abort
7278
7279
7280
7281/* ------------------------------ */
7282    .balign 64
7283.L_OP_BREAKPOINT: /* 0xec */
7284/* File: armv5te/OP_BREAKPOINT.S */
7285/* File: armv5te/unused.S */
7286    bl      common_abort
7287
7288
7289
7290/* ------------------------------ */
7291    .balign 64
7292.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7293/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7294    /*
7295     * Handle a throw-verification-error instruction.  This throws an
7296     * exception for an error discovered during verification.  The
7297     * exception is indicated by AA, with some detail provided by BBBB.
7298     */
7299    /* op AA, ref@BBBB */
7300    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7301    FETCH(r2, 1)                        @ r2<- BBBB
7302    EXPORT_PC()                         @ export the PC
7303    mov     r1, rINST, lsr #8           @ r1<- AA
7304    bl      dvmThrowVerificationError   @ always throws
7305    b       common_exceptionThrown      @ handle exception
7306
7307
7308/* ------------------------------ */
7309    .balign 64
7310.L_OP_EXECUTE_INLINE: /* 0xee */
7311/* File: armv5te/OP_EXECUTE_INLINE.S */
7312    /*
7313     * Execute a "native inline" instruction.
7314     *
7315     * We need to call an InlineOp4Func:
7316     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7317     *
7318     * The first four args are in r0-r3, pointer to return value storage
7319     * is on the stack.  The function's return value is a flag that tells
7320     * us if an exception was thrown.
7321     */
7322    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7323    FETCH(r10, 1)                       @ r10<- BBBB
7324    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7325    EXPORT_PC()                         @ can throw
7326    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7327    mov     r0, rINST, lsr #12          @ r0<- B
7328    str     r1, [sp]                    @ push &glue->retval
7329    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7330    add     sp, sp, #8                  @ pop stack
7331    cmp     r0, #0                      @ test boolean result of inline
7332    beq     common_exceptionThrown      @ returned false, handle exception
7333    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7334    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7335    GOTO_OPCODE(ip)                     @ jump to next instruction
7336
7337/* ------------------------------ */
7338    .balign 64
7339.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7340/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7341    /*
7342     * Execute a "native inline" instruction, using "/range" semantics.
7343     * Same idea as execute-inline, but we get the args differently.
7344     *
7345     * We need to call an InlineOp4Func:
7346     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7347     *
7348     * The first four args are in r0-r3, pointer to return value storage
7349     * is on the stack.  The function's return value is a flag that tells
7350     * us if an exception was thrown.
7351     */
7352    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7353    FETCH(r10, 1)                       @ r10<- BBBB
7354    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7355    EXPORT_PC()                         @ can throw
7356    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7357    mov     r0, rINST, lsr #8           @ r0<- AA
7358    str     r1, [sp]                    @ push &glue->retval
7359    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7360    add     sp, sp, #8                  @ pop stack
7361    cmp     r0, #0                      @ test boolean result of inline
7362    beq     common_exceptionThrown      @ returned false, handle exception
7363    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7364    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7365    GOTO_OPCODE(ip)                     @ jump to next instruction
7366
7367/* ------------------------------ */
7368    .balign 64
7369.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7370/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7371    /*
7372     * invoke-direct-empty is a no-op in a "standard" interpreter.
7373     */
7374    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7375    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7376    GOTO_OPCODE(ip)                     @ execute it
7377
7378/* ------------------------------ */
7379    .balign 64
7380.L_OP_UNUSED_F1: /* 0xf1 */
7381/* File: armv5te/OP_UNUSED_F1.S */
7382/* File: armv5te/unused.S */
7383    bl      common_abort
7384
7385
7386
7387/* ------------------------------ */
7388    .balign 64
7389.L_OP_IGET_QUICK: /* 0xf2 */
7390/* File: armv5te/OP_IGET_QUICK.S */
7391    /* For: iget-quick, iget-object-quick */
7392    /* op vA, vB, offset@CCCC */
7393    mov     r2, rINST, lsr #12          @ r2<- B
7394    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7395    FETCH(r1, 1)                        @ r1<- field byte offset
7396    cmp     r3, #0                      @ check object for null
7397    mov     r2, rINST, lsr #8           @ r2<- A(+)
7398    beq     common_errNullObject        @ object was null
7399    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7401    and     r2, r2, #15
7402    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7403    SET_VREG(r0, r2)                    @ fp[A]<- r0
7404    GOTO_OPCODE(ip)                     @ jump to next instruction
7405
7406
7407/* ------------------------------ */
7408    .balign 64
7409.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7410/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7411    /* iget-wide-quick vA, vB, offset@CCCC */
7412    mov     r2, rINST, lsr #12          @ r2<- B
7413    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7414    FETCH(r1, 1)                        @ r1<- field byte offset
7415    cmp     r3, #0                      @ check object for null
7416    mov     r2, rINST, lsr #8           @ r2<- A(+)
7417    beq     common_errNullObject        @ object was null
7418    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7419    and     r2, r2, #15
7420    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7421    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7423    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7424    GOTO_OPCODE(ip)                     @ jump to next instruction
7425
7426
7427/* ------------------------------ */
7428    .balign 64
7429.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7430/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7431/* File: armv5te/OP_IGET_QUICK.S */
7432    /* For: iget-quick, iget-object-quick */
7433    /* op vA, vB, offset@CCCC */
7434    mov     r2, rINST, lsr #12          @ r2<- B
7435    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7436    FETCH(r1, 1)                        @ r1<- field byte offset
7437    cmp     r3, #0                      @ check object for null
7438    mov     r2, rINST, lsr #8           @ r2<- A(+)
7439    beq     common_errNullObject        @ object was null
7440    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7441    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7442    and     r2, r2, #15
7443    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7444    SET_VREG(r0, r2)                    @ fp[A]<- r0
7445    GOTO_OPCODE(ip)                     @ jump to next instruction
7446
7447
7448
7449/* ------------------------------ */
7450    .balign 64
7451.L_OP_IPUT_QUICK: /* 0xf5 */
7452/* File: armv5te/OP_IPUT_QUICK.S */
7453    /* For: iput-quick, iput-object-quick */
7454    /* op vA, vB, offset@CCCC */
7455    mov     r2, rINST, lsr #12          @ r2<- B
7456    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7457    FETCH(r1, 1)                        @ r1<- field byte offset
7458    cmp     r3, #0                      @ check object for null
7459    mov     r2, rINST, lsr #8           @ r2<- A(+)
7460    beq     common_errNullObject        @ object was null
7461    and     r2, r2, #15
7462    GET_VREG(r0, r2)                    @ r0<- fp[A]
7463    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7464    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7465    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7466    GOTO_OPCODE(ip)                     @ jump to next instruction
7467
7468
7469/* ------------------------------ */
7470    .balign 64
7471.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7472/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7473    /* iput-wide-quick vA, vB, offset@CCCC */
7474    mov     r0, rINST, lsr #8           @ r0<- A(+)
7475    mov     r1, rINST, lsr #12          @ r1<- B
7476    and     r0, r0, #15
7477    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7478    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7479    cmp     r2, #0                      @ check object for null
7480    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7481    beq     common_errNullObject        @ object was null
7482    FETCH(r3, 1)                        @ r3<- field byte offset
7483    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7484    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7486    GOTO_OPCODE(ip)                     @ jump to next instruction
7487
7488
7489/* ------------------------------ */
7490    .balign 64
7491.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7492/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7493/* File: armv5te/OP_IPUT_QUICK.S */
7494    /* For: iput-quick, iput-object-quick */
7495    /* op vA, vB, offset@CCCC */
7496    mov     r2, rINST, lsr #12          @ r2<- B
7497    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7498    FETCH(r1, 1)                        @ r1<- field byte offset
7499    cmp     r3, #0                      @ check object for null
7500    mov     r2, rINST, lsr #8           @ r2<- A(+)
7501    beq     common_errNullObject        @ object was null
7502    and     r2, r2, #15
7503    GET_VREG(r0, r2)                    @ r0<- fp[A]
7504    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7505    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7506    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7507    GOTO_OPCODE(ip)                     @ jump to next instruction
7508
7509
7510
7511/* ------------------------------ */
7512    .balign 64
7513.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7514/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7515    /*
7516     * Handle an optimized virtual method call.
7517     *
7518     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7519     */
7520    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7521    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7522    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7523    FETCH(r1, 1)                        @ r1<- BBBB
7524    .if     (!0)
7525    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7526    .endif
7527    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7528    cmp     r2, #0                      @ is "this" null?
7529    beq     common_errNullObject        @ null "this", throw exception
7530    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7531    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7532    EXPORT_PC()                         @ invoke must export
7533    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7534    bl      common_invokeMethodNoRange @ continue on
7535
7536/* ------------------------------ */
7537    .balign 64
7538.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7539/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7540/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7541    /*
7542     * Handle an optimized virtual method call.
7543     *
7544     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7545     */
7546    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7547    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7548    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7549    FETCH(r1, 1)                        @ r1<- BBBB
7550    .if     (!1)
7551    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7552    .endif
7553    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7554    cmp     r2, #0                      @ is "this" null?
7555    beq     common_errNullObject        @ null "this", throw exception
7556    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7557    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7558    EXPORT_PC()                         @ invoke must export
7559    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7560    bl      common_invokeMethodRange @ continue on
7561
7562
7563/* ------------------------------ */
7564    .balign 64
7565.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7566/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7567    /*
7568     * Handle an optimized "super" method call.
7569     *
7570     * for: [opt] invoke-super-quick, invoke-super-quick/range
7571     */
7572    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7573    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7574    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7575    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7576    .if     (!0)
7577    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7578    .endif
7579    FETCH(r1, 1)                        @ r1<- BBBB
7580    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7581    EXPORT_PC()                         @ must export for invoke
7582    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7583    GET_VREG(r3, r10)                   @ r3<- "this"
7584    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7585    cmp     r3, #0                      @ null "this" ref?
7586    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7587    beq     common_errNullObject        @ "this" is null, throw exception
7588    bl      common_invokeMethodNoRange @ continue on
7589
7590
7591/* ------------------------------ */
7592    .balign 64
7593.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7594/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7595/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7596    /*
7597     * Handle an optimized "super" method call.
7598     *
7599     * for: [opt] invoke-super-quick, invoke-super-quick/range
7600     */
7601    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7602    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7603    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7604    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7605    .if     (!1)
7606    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7607    .endif
7608    FETCH(r1, 1)                        @ r1<- BBBB
7609    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7610    EXPORT_PC()                         @ must export for invoke
7611    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7612    GET_VREG(r3, r10)                   @ r3<- "this"
7613    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7614    cmp     r3, #0                      @ null "this" ref?
7615    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7616    beq     common_errNullObject        @ "this" is null, throw exception
7617    bl      common_invokeMethodRange @ continue on
7618
7619
7620
7621/* ------------------------------ */
7622    .balign 64
7623.L_OP_UNUSED_FC: /* 0xfc */
7624/* File: armv5te/OP_UNUSED_FC.S */
7625/* File: armv5te/unused.S */
7626    bl      common_abort
7627
7628
7629
7630/* ------------------------------ */
7631    .balign 64
7632.L_OP_UNUSED_FD: /* 0xfd */
7633/* File: armv5te/OP_UNUSED_FD.S */
7634/* File: armv5te/unused.S */
7635    bl      common_abort
7636
7637
7638
7639/* ------------------------------ */
7640    .balign 64
7641.L_OP_UNUSED_FE: /* 0xfe */
7642/* File: armv5te/OP_UNUSED_FE.S */
7643/* File: armv5te/unused.S */
7644    bl      common_abort
7645
7646
7647
7648/* ------------------------------ */
7649    .balign 64
7650.L_OP_UNUSED_FF: /* 0xff */
7651/* File: armv5te/OP_UNUSED_FF.S */
7652/* File: armv5te/unused.S */
7653    bl      common_abort
7654
7655
7656
7657
7658    .balign 64
7659    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7660    .global dvmAsmInstructionEnd
7661dvmAsmInstructionEnd:
7662
7663/*
7664 * ===========================================================================
7665 *  Sister implementations
7666 * ===========================================================================
7667 */
7668    .global dvmAsmSisterStart
7669    .type   dvmAsmSisterStart, %function
7670    .text
7671    .balign 4
7672dvmAsmSisterStart:
7673
7674/* continuation for OP_CONST_STRING */
7675
7676    /*
7677     * Continuation if the String has not yet been resolved.
7678     *  r1: BBBB (String ref)
7679     *  r9: target register
7680     */
7681.LOP_CONST_STRING_resolve:
7682    EXPORT_PC()
7683    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7684    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7685    bl      dvmResolveString            @ r0<- String reference
7686    cmp     r0, #0                      @ failed?
7687    beq     common_exceptionThrown      @ yup, handle the exception
7688    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7689    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7690    SET_VREG(r0, r9)                    @ vAA<- r0
7691    GOTO_OPCODE(ip)                     @ jump to next instruction
7692
7693
7694/* continuation for OP_CONST_STRING_JUMBO */
7695
7696    /*
7697     * Continuation if the String has not yet been resolved.
7698     *  r1: BBBBBBBB (String ref)
7699     *  r9: target register
7700     */
7701.LOP_CONST_STRING_JUMBO_resolve:
7702    EXPORT_PC()
7703    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7704    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7705    bl      dvmResolveString            @ r0<- String reference
7706    cmp     r0, #0                      @ failed?
7707    beq     common_exceptionThrown      @ yup, handle the exception
7708    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7709    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7710    SET_VREG(r0, r9)                    @ vAA<- r0
7711    GOTO_OPCODE(ip)                     @ jump to next instruction
7712
7713
7714/* continuation for OP_CONST_CLASS */
7715
7716    /*
7717     * Continuation if the Class has not yet been resolved.
7718     *  r1: BBBB (Class ref)
7719     *  r9: target register
7720     */
7721.LOP_CONST_CLASS_resolve:
7722    EXPORT_PC()
7723    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7724    mov     r2, #1                      @ r2<- true
7725    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7726    bl      dvmResolveClass             @ r0<- Class reference
7727    cmp     r0, #0                      @ failed?
7728    beq     common_exceptionThrown      @ yup, handle the exception
7729    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7731    SET_VREG(r0, r9)                    @ vAA<- r0
7732    GOTO_OPCODE(ip)                     @ jump to next instruction
7733
7734
7735/* continuation for OP_CHECK_CAST */
7736
7737    /*
7738     * Trivial test failed, need to perform full check.  This is common.
7739     *  r0 holds obj->clazz
7740     *  r1 holds class resolved from BBBB
7741     *  r9 holds object
7742     */
7743.LOP_CHECK_CAST_fullcheck:
7744    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7745    cmp     r0, #0                      @ failed?
7746    bne     .LOP_CHECK_CAST_okay            @ no, success
7747
7748    @ A cast has failed.  We need to throw a ClassCastException with the
7749    @ class of the object that failed to be cast.
7750    EXPORT_PC()                         @ about to throw
7751    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7752    ldr     r0, .LstrClassCastExceptionPtr
7753    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7754    bl      dvmThrowExceptionWithClassMessage
7755    b       common_exceptionThrown
7756
7757    /*
7758     * Resolution required.  This is the least-likely path.
7759     *
7760     *  r2 holds BBBB
7761     *  r9 holds object
7762     */
7763.LOP_CHECK_CAST_resolve:
7764    EXPORT_PC()                         @ resolve() could throw
7765    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7766    mov     r1, r2                      @ r1<- BBBB
7767    mov     r2, #0                      @ r2<- false
7768    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7769    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7770    cmp     r0, #0                      @ got null?
7771    beq     common_exceptionThrown      @ yes, handle exception
7772    mov     r1, r0                      @ r1<- class resolved from BBB
7773    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7774    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7775
7776.LstrClassCastExceptionPtr:
7777    .word   .LstrClassCastException
7778
7779
7780/* continuation for OP_INSTANCE_OF */
7781
7782    /*
7783     * Trivial test failed, need to perform full check.  This is common.
7784     *  r0 holds obj->clazz
7785     *  r1 holds class resolved from BBBB
7786     *  r9 holds A
7787     */
7788.LOP_INSTANCE_OF_fullcheck:
7789    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7790    @ fall through to OP_INSTANCE_OF_store
7791
7792    /*
7793     * r0 holds boolean result
7794     * r9 holds A
7795     */
7796.LOP_INSTANCE_OF_store:
7797    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7798    SET_VREG(r0, r9)                    @ vA<- r0
7799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7800    GOTO_OPCODE(ip)                     @ jump to next instruction
7801
7802    /*
7803     * Trivial test succeeded, save and bail.
7804     *  r9 holds A
7805     */
7806.LOP_INSTANCE_OF_trivial:
7807    mov     r0, #1                      @ indicate success
7808    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7809    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7810    SET_VREG(r0, r9)                    @ vA<- r0
7811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7812    GOTO_OPCODE(ip)                     @ jump to next instruction
7813
7814    /*
7815     * Resolution required.  This is the least-likely path.
7816     *
7817     *  r3 holds BBBB
7818     *  r9 holds A
7819     */
7820.LOP_INSTANCE_OF_resolve:
7821    EXPORT_PC()                         @ resolve() could throw
7822    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7823    mov     r1, r3                      @ r1<- BBBB
7824    mov     r2, #1                      @ r2<- true
7825    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7826    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7827    cmp     r0, #0                      @ got null?
7828    beq     common_exceptionThrown      @ yes, handle exception
7829    mov     r1, r0                      @ r1<- class resolved from BBB
7830    mov     r3, rINST, lsr #12          @ r3<- B
7831    GET_VREG(r0, r3)                    @ r0<- vB (object)
7832    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7833    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7834
7835
7836/* continuation for OP_NEW_INSTANCE */
7837
7838    .balign 32                          @ minimize cache lines
7839.LOP_NEW_INSTANCE_finish: @ r0=new object
7840    mov     r3, rINST, lsr #8           @ r3<- AA
7841    cmp     r0, #0                      @ failed?
7842    beq     common_exceptionThrown      @ yes, handle the exception
7843    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7845    SET_VREG(r0, r3)                    @ vAA<- r0
7846    GOTO_OPCODE(ip)                     @ jump to next instruction
7847
7848    /*
7849     * Class initialization required.
7850     *
7851     *  r0 holds class object
7852     */
7853.LOP_NEW_INSTANCE_needinit:
7854    mov     r9, r0                      @ save r0
7855    bl      dvmInitClass                @ initialize class
7856    cmp     r0, #0                      @ check boolean result
7857    mov     r0, r9                      @ restore r0
7858    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7859    b       common_exceptionThrown      @ failed, deal with init exception
7860
7861    /*
7862     * Resolution required.  This is the least-likely path.
7863     *
7864     *  r1 holds BBBB
7865     */
7866.LOP_NEW_INSTANCE_resolve:
7867    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7868    mov     r2, #0                      @ r2<- false
7869    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7870    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7871    cmp     r0, #0                      @ got null?
7872    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7873    b       common_exceptionThrown      @ yes, handle exception
7874
7875.LstrInstantiationErrorPtr:
7876    .word   .LstrInstantiationError
7877
7878
7879/* continuation for OP_NEW_ARRAY */
7880
7881
7882    /*
7883     * Resolve class.  (This is an uncommon case.)
7884     *
7885     *  r1 holds array length
7886     *  r2 holds class ref CCCC
7887     */
7888.LOP_NEW_ARRAY_resolve:
7889    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7890    mov     r9, r1                      @ r9<- length (save)
7891    mov     r1, r2                      @ r1<- CCCC
7892    mov     r2, #0                      @ r2<- false
7893    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7894    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7895    cmp     r0, #0                      @ got null?
7896    mov     r1, r9                      @ r1<- length (restore)
7897    beq     common_exceptionThrown      @ yes, handle exception
7898    @ fall through to OP_NEW_ARRAY_finish
7899
7900    /*
7901     * Finish allocation.
7902     *
7903     *  r0 holds class
7904     *  r1 holds array length
7905     */
7906.LOP_NEW_ARRAY_finish:
7907    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7908    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7909    cmp     r0, #0                      @ failed?
7910    mov     r2, rINST, lsr #8           @ r2<- A+
7911    beq     common_exceptionThrown      @ yes, handle the exception
7912    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7913    and     r2, r2, #15                 @ r2<- A
7914    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7915    SET_VREG(r0, r2)                    @ vA<- r0
7916    GOTO_OPCODE(ip)                     @ jump to next instruction
7917
7918
7919/* continuation for OP_FILLED_NEW_ARRAY */
7920
7921    /*
7922     * On entry:
7923     *  r0 holds array class
7924     *  r10 holds AA or BA
7925     */
7926.LOP_FILLED_NEW_ARRAY_continue:
7927    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7928    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7929    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7930    .if     0
7931    mov     r1, r10                     @ r1<- AA (length)
7932    .else
7933    mov     r1, r10, lsr #4             @ r1<- B (length)
7934    .endif
7935    cmp     r3, #'I'                    @ array of ints?
7936    cmpne   r3, #'L'                    @ array of objects?
7937    cmpne   r3, #'['                    @ array of arrays?
7938    mov     r9, r1                      @ save length in r9
7939    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7940    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7941    cmp     r0, #0                      @ null return?
7942    beq     common_exceptionThrown      @ alloc failed, handle exception
7943
7944    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7945    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7946    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7947    subs    r9, r9, #1                  @ length--, check for neg
7948    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7949    bmi     2f                          @ was zero, bail
7950
7951    @ copy values from registers into the array
7952    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7953    .if     0
7954    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79551:  ldr     r3, [r2], #4                @ r3<- *r2++
7956    subs    r9, r9, #1                  @ count--
7957    str     r3, [r0], #4                @ *contents++ = vX
7958    bpl     1b
7959    @ continue at 2
7960    .else
7961    cmp     r9, #4                      @ length was initially 5?
7962    and     r2, r10, #15                @ r2<- A
7963    bne     1f                          @ <= 4 args, branch
7964    GET_VREG(r3, r2)                    @ r3<- vA
7965    sub     r9, r9, #1                  @ count--
7966    str     r3, [r0, #16]               @ contents[4] = vA
79671:  and     r2, r1, #15                 @ r2<- F/E/D/C
7968    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7969    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7970    subs    r9, r9, #1                  @ count--
7971    str     r3, [r0], #4                @ *contents++ = vX
7972    bpl     1b
7973    @ continue at 2
7974    .endif
7975
79762:
7977    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7978    GOTO_OPCODE(ip)                     @ execute it
7979
7980    /*
7981     * Throw an exception indicating that we have not implemented this
7982     * mode of filled-new-array.
7983     */
7984.LOP_FILLED_NEW_ARRAY_notimpl:
7985    ldr     r0, .L_strInternalError
7986    ldr     r1, .L_strFilledNewArrayNotImpl
7987    bl      dvmThrowException
7988    b       common_exceptionThrown
7989
7990    .if     (!0)                 @ define in one or the other, not both
7991.L_strFilledNewArrayNotImpl:
7992    .word   .LstrFilledNewArrayNotImpl
7993.L_strInternalError:
7994    .word   .LstrInternalError
7995    .endif
7996
7997
7998/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7999
8000    /*
8001     * On entry:
8002     *  r0 holds array class
8003     *  r10 holds AA or BA
8004     */
8005.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8006    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8007    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8008    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8009    .if     1
8010    mov     r1, r10                     @ r1<- AA (length)
8011    .else
8012    mov     r1, r10, lsr #4             @ r1<- B (length)
8013    .endif
8014    cmp     r3, #'I'                    @ array of ints?
8015    cmpne   r3, #'L'                    @ array of objects?
8016    cmpne   r3, #'['                    @ array of arrays?
8017    mov     r9, r1                      @ save length in r9
8018    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8019    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8020    cmp     r0, #0                      @ null return?
8021    beq     common_exceptionThrown      @ alloc failed, handle exception
8022
8023    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8024    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8025    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8026    subs    r9, r9, #1                  @ length--, check for neg
8027    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8028    bmi     2f                          @ was zero, bail
8029
8030    @ copy values from registers into the array
8031    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8032    .if     1
8033    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80341:  ldr     r3, [r2], #4                @ r3<- *r2++
8035    subs    r9, r9, #1                  @ count--
8036    str     r3, [r0], #4                @ *contents++ = vX
8037    bpl     1b
8038    @ continue at 2
8039    .else
8040    cmp     r9, #4                      @ length was initially 5?
8041    and     r2, r10, #15                @ r2<- A
8042    bne     1f                          @ <= 4 args, branch
8043    GET_VREG(r3, r2)                    @ r3<- vA
8044    sub     r9, r9, #1                  @ count--
8045    str     r3, [r0, #16]               @ contents[4] = vA
80461:  and     r2, r1, #15                 @ r2<- F/E/D/C
8047    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8048    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8049    subs    r9, r9, #1                  @ count--
8050    str     r3, [r0], #4                @ *contents++ = vX
8051    bpl     1b
8052    @ continue at 2
8053    .endif
8054
80552:
8056    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8057    GOTO_OPCODE(ip)                     @ execute it
8058
8059    /*
8060     * Throw an exception indicating that we have not implemented this
8061     * mode of filled-new-array.
8062     */
8063.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8064    ldr     r0, .L_strInternalError
8065    ldr     r1, .L_strFilledNewArrayNotImpl
8066    bl      dvmThrowException
8067    b       common_exceptionThrown
8068
8069    .if     (!1)                 @ define in one or the other, not both
8070.L_strFilledNewArrayNotImpl:
8071    .word   .LstrFilledNewArrayNotImpl
8072.L_strInternalError:
8073    .word   .LstrInternalError
8074    .endif
8075
8076
8077/* continuation for OP_CMPL_FLOAT */
8078.LOP_CMPL_FLOAT_finish:
8079    SET_VREG(r0, r9)                    @ vAA<- r0
8080    GOTO_OPCODE(ip)                     @ jump to next instruction
8081
8082
8083/* continuation for OP_CMPG_FLOAT */
8084.LOP_CMPG_FLOAT_finish:
8085    SET_VREG(r0, r9)                    @ vAA<- r0
8086    GOTO_OPCODE(ip)                     @ jump to next instruction
8087
8088
8089/* continuation for OP_CMPL_DOUBLE */
8090.LOP_CMPL_DOUBLE_finish:
8091    SET_VREG(r0, r9)                    @ vAA<- r0
8092    GOTO_OPCODE(ip)                     @ jump to next instruction
8093
8094
8095/* continuation for OP_CMPG_DOUBLE */
8096.LOP_CMPG_DOUBLE_finish:
8097    SET_VREG(r0, r9)                    @ vAA<- r0
8098    GOTO_OPCODE(ip)                     @ jump to next instruction
8099
8100
8101/* continuation for OP_CMP_LONG */
8102
8103.LOP_CMP_LONG_less:
8104    mvn     r1, #0                      @ r1<- -1
8105    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8106    @ instead, we just replicate the tail end.
8107    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8108    SET_VREG(r1, r9)                    @ vAA<- r1
8109    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8110    GOTO_OPCODE(ip)                     @ jump to next instruction
8111
8112.LOP_CMP_LONG_greater:
8113    mov     r1, #1                      @ r1<- 1
8114    @ fall through to _finish
8115
8116.LOP_CMP_LONG_finish:
8117    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8118    SET_VREG(r1, r9)                    @ vAA<- r1
8119    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8120    GOTO_OPCODE(ip)                     @ jump to next instruction
8121
8122
8123/* continuation for OP_AGET_WIDE */
8124
8125.LOP_AGET_WIDE_finish:
8126    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8127    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8128    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8130    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8131    GOTO_OPCODE(ip)                     @ jump to next instruction
8132
8133
8134/* continuation for OP_APUT_WIDE */
8135
8136.LOP_APUT_WIDE_finish:
8137    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8138    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8139    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8140    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8141    GOTO_OPCODE(ip)                     @ jump to next instruction
8142
8143
8144/* continuation for OP_APUT_OBJECT */
8145    /*
8146     * On entry:
8147     *  r1 = vBB (arrayObj)
8148     *  r9 = vAA (obj)
8149     *  r10 = offset into array (vBB + vCC * width)
8150     */
8151.LOP_APUT_OBJECT_finish:
8152    cmp     r9, #0                      @ storing null reference?
8153    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8154    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8155    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8156    bl      dvmCanPutArrayElement       @ test object type vs. array type
8157    cmp     r0, #0                      @ okay?
8158    beq     common_errArrayStore        @ no
8159.LOP_APUT_OBJECT_skip_check:
8160    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8162    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8163    GOTO_OPCODE(ip)                     @ jump to next instruction
8164
8165
8166/* continuation for OP_IGET */
8167
8168    /*
8169     * Currently:
8170     *  r0 holds resolved field
8171     *  r9 holds object
8172     */
8173.LOP_IGET_finish:
8174    @bl      common_squeak0
8175    cmp     r9, #0                      @ check object for null
8176    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8177    beq     common_errNullObject        @ object was null
8178    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8179    mov     r2, rINST, lsr #8           @ r2<- A+
8180    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8181    and     r2, r2, #15                 @ r2<- A
8182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8183    SET_VREG(r0, r2)                    @ fp[A]<- r0
8184    GOTO_OPCODE(ip)                     @ jump to next instruction
8185
8186
8187/* continuation for OP_IGET_WIDE */
8188
8189    /*
8190     * Currently:
8191     *  r0 holds resolved field
8192     *  r9 holds object
8193     */
8194.LOP_IGET_WIDE_finish:
8195    cmp     r9, #0                      @ check object for null
8196    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8197    beq     common_errNullObject        @ object was null
8198    mov     r2, rINST, lsr #8           @ r2<- A+
8199    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8200    and     r2, r2, #15                 @ r2<- A
8201    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8202    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8204    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8205    GOTO_OPCODE(ip)                     @ jump to next instruction
8206
8207
8208/* continuation for OP_IGET_OBJECT */
8209
8210    /*
8211     * Currently:
8212     *  r0 holds resolved field
8213     *  r9 holds object
8214     */
8215.LOP_IGET_OBJECT_finish:
8216    @bl      common_squeak0
8217    cmp     r9, #0                      @ check object for null
8218    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8219    beq     common_errNullObject        @ object was null
8220    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8221    mov     r2, rINST, lsr #8           @ r2<- A+
8222    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8223    and     r2, r2, #15                 @ r2<- A
8224    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8225    SET_VREG(r0, r2)                    @ fp[A]<- r0
8226    GOTO_OPCODE(ip)                     @ jump to next instruction
8227
8228
8229/* continuation for OP_IGET_BOOLEAN */
8230
8231    /*
8232     * Currently:
8233     *  r0 holds resolved field
8234     *  r9 holds object
8235     */
8236.LOP_IGET_BOOLEAN_finish:
8237    @bl      common_squeak1
8238    cmp     r9, #0                      @ check object for null
8239    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8240    beq     common_errNullObject        @ object was null
8241    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8242    mov     r2, rINST, lsr #8           @ r2<- A+
8243    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8244    and     r2, r2, #15                 @ r2<- A
8245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8246    SET_VREG(r0, r2)                    @ fp[A]<- r0
8247    GOTO_OPCODE(ip)                     @ jump to next instruction
8248
8249
8250/* continuation for OP_IGET_BYTE */
8251
8252    /*
8253     * Currently:
8254     *  r0 holds resolved field
8255     *  r9 holds object
8256     */
8257.LOP_IGET_BYTE_finish:
8258    @bl      common_squeak2
8259    cmp     r9, #0                      @ check object for null
8260    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8261    beq     common_errNullObject        @ object was null
8262    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8263    mov     r2, rINST, lsr #8           @ r2<- A+
8264    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8265    and     r2, r2, #15                 @ r2<- A
8266    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8267    SET_VREG(r0, r2)                    @ fp[A]<- r0
8268    GOTO_OPCODE(ip)                     @ jump to next instruction
8269
8270
8271/* continuation for OP_IGET_CHAR */
8272
8273    /*
8274     * Currently:
8275     *  r0 holds resolved field
8276     *  r9 holds object
8277     */
8278.LOP_IGET_CHAR_finish:
8279    @bl      common_squeak3
8280    cmp     r9, #0                      @ check object for null
8281    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8282    beq     common_errNullObject        @ object was null
8283    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8284    mov     r2, rINST, lsr #8           @ r2<- A+
8285    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8286    and     r2, r2, #15                 @ r2<- A
8287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8288    SET_VREG(r0, r2)                    @ fp[A]<- r0
8289    GOTO_OPCODE(ip)                     @ jump to next instruction
8290
8291
8292/* continuation for OP_IGET_SHORT */
8293
8294    /*
8295     * Currently:
8296     *  r0 holds resolved field
8297     *  r9 holds object
8298     */
8299.LOP_IGET_SHORT_finish:
8300    @bl      common_squeak4
8301    cmp     r9, #0                      @ check object for null
8302    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8303    beq     common_errNullObject        @ object was null
8304    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8305    mov     r2, rINST, lsr #8           @ r2<- A+
8306    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8307    and     r2, r2, #15                 @ r2<- A
8308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8309    SET_VREG(r0, r2)                    @ fp[A]<- r0
8310    GOTO_OPCODE(ip)                     @ jump to next instruction
8311
8312
8313/* continuation for OP_IPUT */
8314
8315    /*
8316     * Currently:
8317     *  r0 holds resolved field
8318     *  r9 holds object
8319     */
8320.LOP_IPUT_finish:
8321    @bl      common_squeak0
8322    mov     r1, rINST, lsr #8           @ r1<- A+
8323    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8324    and     r1, r1, #15                 @ r1<- A
8325    cmp     r9, #0                      @ check object for null
8326    GET_VREG(r0, r1)                    @ r0<- fp[A]
8327    beq     common_errNullObject        @ object was null
8328    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8329    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8330    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8331    GOTO_OPCODE(ip)                     @ jump to next instruction
8332
8333
8334/* continuation for OP_IPUT_WIDE */
8335
8336    /*
8337     * Currently:
8338     *  r0 holds resolved field
8339     *  r9 holds object
8340     */
8341.LOP_IPUT_WIDE_finish:
8342    mov     r2, rINST, lsr #8           @ r2<- A+
8343    cmp     r9, #0                      @ check object for null
8344    and     r2, r2, #15                 @ r2<- A
8345    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8346    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8347    beq     common_errNullObject        @ object was null
8348    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8349    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8350    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8351    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8352    GOTO_OPCODE(ip)                     @ jump to next instruction
8353
8354
8355/* continuation for OP_IPUT_OBJECT */
8356
8357    /*
8358     * Currently:
8359     *  r0 holds resolved field
8360     *  r9 holds object
8361     */
8362.LOP_IPUT_OBJECT_finish:
8363    @bl      common_squeak0
8364    mov     r1, rINST, lsr #8           @ r1<- A+
8365    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8366    and     r1, r1, #15                 @ r1<- A
8367    cmp     r9, #0                      @ check object for null
8368    GET_VREG(r0, r1)                    @ r0<- fp[A]
8369    beq     common_errNullObject        @ object was null
8370    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8371    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8372    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8373    GOTO_OPCODE(ip)                     @ jump to next instruction
8374
8375
8376/* continuation for OP_IPUT_BOOLEAN */
8377
8378    /*
8379     * Currently:
8380     *  r0 holds resolved field
8381     *  r9 holds object
8382     */
8383.LOP_IPUT_BOOLEAN_finish:
8384    @bl      common_squeak1
8385    mov     r1, rINST, lsr #8           @ r1<- A+
8386    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8387    and     r1, r1, #15                 @ r1<- A
8388    cmp     r9, #0                      @ check object for null
8389    GET_VREG(r0, r1)                    @ r0<- fp[A]
8390    beq     common_errNullObject        @ object was null
8391    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8392    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8393    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8394    GOTO_OPCODE(ip)                     @ jump to next instruction
8395
8396
8397/* continuation for OP_IPUT_BYTE */
8398
8399    /*
8400     * Currently:
8401     *  r0 holds resolved field
8402     *  r9 holds object
8403     */
8404.LOP_IPUT_BYTE_finish:
8405    @bl      common_squeak2
8406    mov     r1, rINST, lsr #8           @ r1<- A+
8407    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8408    and     r1, r1, #15                 @ r1<- A
8409    cmp     r9, #0                      @ check object for null
8410    GET_VREG(r0, r1)                    @ r0<- fp[A]
8411    beq     common_errNullObject        @ object was null
8412    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8413    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8414    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8415    GOTO_OPCODE(ip)                     @ jump to next instruction
8416
8417
8418/* continuation for OP_IPUT_CHAR */
8419
8420    /*
8421     * Currently:
8422     *  r0 holds resolved field
8423     *  r9 holds object
8424     */
8425.LOP_IPUT_CHAR_finish:
8426    @bl      common_squeak3
8427    mov     r1, rINST, lsr #8           @ r1<- A+
8428    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8429    and     r1, r1, #15                 @ r1<- A
8430    cmp     r9, #0                      @ check object for null
8431    GET_VREG(r0, r1)                    @ r0<- fp[A]
8432    beq     common_errNullObject        @ object was null
8433    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8434    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8435    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8436    GOTO_OPCODE(ip)                     @ jump to next instruction
8437
8438
8439/* continuation for OP_IPUT_SHORT */
8440
8441    /*
8442     * Currently:
8443     *  r0 holds resolved field
8444     *  r9 holds object
8445     */
8446.LOP_IPUT_SHORT_finish:
8447    @bl      common_squeak4
8448    mov     r1, rINST, lsr #8           @ r1<- A+
8449    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8450    and     r1, r1, #15                 @ r1<- A
8451    cmp     r9, #0                      @ check object for null
8452    GET_VREG(r0, r1)                    @ r0<- fp[A]
8453    beq     common_errNullObject        @ object was null
8454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8456    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8457    GOTO_OPCODE(ip)                     @ jump to next instruction
8458
8459
8460/* continuation for OP_SGET */
8461
8462    /*
8463     * Continuation if the field has not yet been resolved.
8464     *  r1: BBBB field ref
8465     */
8466.LOP_SGET_resolve:
8467    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8468    EXPORT_PC()                         @ resolve() could throw, so export now
8469    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8470    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8471    cmp     r0, #0                      @ success?
8472    bne     .LOP_SGET_finish          @ yes, finish
8473    b       common_exceptionThrown      @ no, handle exception
8474
8475
8476/* continuation for OP_SGET_WIDE */
8477
8478    /*
8479     * Continuation if the field has not yet been resolved.
8480     *  r1: BBBB field ref
8481     */
8482.LOP_SGET_WIDE_resolve:
8483    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8484    EXPORT_PC()                         @ resolve() could throw, so export now
8485    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8486    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8487    cmp     r0, #0                      @ success?
8488    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8489    b       common_exceptionThrown      @ no, handle exception
8490
8491
8492/* continuation for OP_SGET_OBJECT */
8493
8494    /*
8495     * Continuation if the field has not yet been resolved.
8496     *  r1: BBBB field ref
8497     */
8498.LOP_SGET_OBJECT_resolve:
8499    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8500    EXPORT_PC()                         @ resolve() could throw, so export now
8501    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8502    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8503    cmp     r0, #0                      @ success?
8504    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8505    b       common_exceptionThrown      @ no, handle exception
8506
8507
8508/* continuation for OP_SGET_BOOLEAN */
8509
8510    /*
8511     * Continuation if the field has not yet been resolved.
8512     *  r1: BBBB field ref
8513     */
8514.LOP_SGET_BOOLEAN_resolve:
8515    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8516    EXPORT_PC()                         @ resolve() could throw, so export now
8517    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8518    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8519    cmp     r0, #0                      @ success?
8520    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8521    b       common_exceptionThrown      @ no, handle exception
8522
8523
8524/* continuation for OP_SGET_BYTE */
8525
8526    /*
8527     * Continuation if the field has not yet been resolved.
8528     *  r1: BBBB field ref
8529     */
8530.LOP_SGET_BYTE_resolve:
8531    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8532    EXPORT_PC()                         @ resolve() could throw, so export now
8533    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8534    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8535    cmp     r0, #0                      @ success?
8536    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8537    b       common_exceptionThrown      @ no, handle exception
8538
8539
8540/* continuation for OP_SGET_CHAR */
8541
8542    /*
8543     * Continuation if the field has not yet been resolved.
8544     *  r1: BBBB field ref
8545     */
8546.LOP_SGET_CHAR_resolve:
8547    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8548    EXPORT_PC()                         @ resolve() could throw, so export now
8549    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8550    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8551    cmp     r0, #0                      @ success?
8552    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8553    b       common_exceptionThrown      @ no, handle exception
8554
8555
8556/* continuation for OP_SGET_SHORT */
8557
8558    /*
8559     * Continuation if the field has not yet been resolved.
8560     *  r1: BBBB field ref
8561     */
8562.LOP_SGET_SHORT_resolve:
8563    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8564    EXPORT_PC()                         @ resolve() could throw, so export now
8565    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8566    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8567    cmp     r0, #0                      @ success?
8568    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8569    b       common_exceptionThrown      @ no, handle exception
8570
8571
8572/* continuation for OP_SPUT */
8573
8574    /*
8575     * Continuation if the field has not yet been resolved.
8576     *  r1: BBBB field ref
8577     */
8578.LOP_SPUT_resolve:
8579    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8580    EXPORT_PC()                         @ resolve() could throw, so export now
8581    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8582    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8583    cmp     r0, #0                      @ success?
8584    bne     .LOP_SPUT_finish          @ yes, finish
8585    b       common_exceptionThrown      @ no, handle exception
8586
8587
8588/* continuation for OP_SPUT_WIDE */
8589
8590    /*
8591     * Continuation if the field has not yet been resolved.
8592     *  r1: BBBB field ref
8593     *  r9: &fp[AA]
8594     */
8595.LOP_SPUT_WIDE_resolve:
8596    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8597    EXPORT_PC()                         @ resolve() could throw, so export now
8598    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8599    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8600    cmp     r0, #0                      @ success?
8601    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8602    b       common_exceptionThrown      @ no, handle exception
8603
8604
8605/* continuation for OP_SPUT_OBJECT */
8606
8607    /*
8608     * Continuation if the field has not yet been resolved.
8609     *  r1: BBBB field ref
8610     */
8611.LOP_SPUT_OBJECT_resolve:
8612    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8613    EXPORT_PC()                         @ resolve() could throw, so export now
8614    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8615    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8616    cmp     r0, #0                      @ success?
8617    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8618    b       common_exceptionThrown      @ no, handle exception
8619
8620
8621/* continuation for OP_SPUT_BOOLEAN */
8622
8623    /*
8624     * Continuation if the field has not yet been resolved.
8625     *  r1: BBBB field ref
8626     */
8627.LOP_SPUT_BOOLEAN_resolve:
8628    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8629    EXPORT_PC()                         @ resolve() could throw, so export now
8630    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8631    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8632    cmp     r0, #0                      @ success?
8633    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8634    b       common_exceptionThrown      @ no, handle exception
8635
8636
8637/* continuation for OP_SPUT_BYTE */
8638
8639    /*
8640     * Continuation if the field has not yet been resolved.
8641     *  r1: BBBB field ref
8642     */
8643.LOP_SPUT_BYTE_resolve:
8644    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8645    EXPORT_PC()                         @ resolve() could throw, so export now
8646    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8647    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8648    cmp     r0, #0                      @ success?
8649    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8650    b       common_exceptionThrown      @ no, handle exception
8651
8652
8653/* continuation for OP_SPUT_CHAR */
8654
8655    /*
8656     * Continuation if the field has not yet been resolved.
8657     *  r1: BBBB field ref
8658     */
8659.LOP_SPUT_CHAR_resolve:
8660    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8661    EXPORT_PC()                         @ resolve() could throw, so export now
8662    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8663    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8664    cmp     r0, #0                      @ success?
8665    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8666    b       common_exceptionThrown      @ no, handle exception
8667
8668
8669/* continuation for OP_SPUT_SHORT */
8670
8671    /*
8672     * Continuation if the field has not yet been resolved.
8673     *  r1: BBBB field ref
8674     */
8675.LOP_SPUT_SHORT_resolve:
8676    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8677    EXPORT_PC()                         @ resolve() could throw, so export now
8678    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8679    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8680    cmp     r0, #0                      @ success?
8681    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8682    b       common_exceptionThrown      @ no, handle exception
8683
8684
8685/* continuation for OP_INVOKE_VIRTUAL */
8686
8687    /*
8688     * At this point:
8689     *  r0 = resolved base method
8690     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8691     */
8692.LOP_INVOKE_VIRTUAL_continue:
8693    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8694    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8695    cmp     r1, #0                      @ is "this" null?
8696    beq     common_errNullObject        @ null "this", throw exception
8697    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8698    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8699    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8700    bl      common_invokeMethodNoRange @ continue on
8701
8702
8703/* continuation for OP_INVOKE_SUPER */
8704
8705    /*
8706     * At this point:
8707     *  r0 = resolved base method
8708     *  r9 = method->clazz
8709     */
8710.LOP_INVOKE_SUPER_continue:
8711    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8712    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8713    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8714    EXPORT_PC()                         @ must export for invoke
8715    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8716    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8717    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8718    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8719    bl      common_invokeMethodNoRange @ continue on
8720
8721.LOP_INVOKE_SUPER_resolve:
8722    mov     r0, r9                      @ r0<- method->clazz
8723    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8724    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8725    cmp     r0, #0                      @ got null?
8726    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8727    b       common_exceptionThrown      @ yes, handle exception
8728
8729    /*
8730     * Throw a NoSuchMethodError with the method name as the message.
8731     *  r0 = resolved base method
8732     */
8733.LOP_INVOKE_SUPER_nsm:
8734    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8735    b       common_errNoSuchMethod
8736
8737
8738/* continuation for OP_INVOKE_DIRECT */
8739
8740    /*
8741     * On entry:
8742     *  r1 = reference (BBBB or CCCC)
8743     *  r10 = "this" register
8744     */
8745.LOP_INVOKE_DIRECT_resolve:
8746    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8747    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8748    mov     r2, #METHOD_DIRECT          @ resolver method type
8749    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8750    cmp     r0, #0                      @ got null?
8751    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8752    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8753    b       common_exceptionThrown      @ yes, handle exception
8754
8755
8756/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8757
8758    /*
8759     * At this point:
8760     *  r0 = resolved base method
8761     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8762     */
8763.LOP_INVOKE_VIRTUAL_RANGE_continue:
8764    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8765    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8766    cmp     r1, #0                      @ is "this" null?
8767    beq     common_errNullObject        @ null "this", throw exception
8768    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8769    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8770    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8771    bl      common_invokeMethodRange @ continue on
8772
8773
8774/* continuation for OP_INVOKE_SUPER_RANGE */
8775
8776    /*
8777     * At this point:
8778     *  r0 = resolved base method
8779     *  r9 = method->clazz
8780     */
8781.LOP_INVOKE_SUPER_RANGE_continue:
8782    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8783    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8784    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8785    EXPORT_PC()                         @ must export for invoke
8786    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8787    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8788    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8789    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8790    bl      common_invokeMethodRange @ continue on
8791
8792.LOP_INVOKE_SUPER_RANGE_resolve:
8793    mov     r0, r9                      @ r0<- method->clazz
8794    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8795    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8796    cmp     r0, #0                      @ got null?
8797    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8798    b       common_exceptionThrown      @ yes, handle exception
8799
8800    /*
8801     * Throw a NoSuchMethodError with the method name as the message.
8802     *  r0 = resolved base method
8803     */
8804.LOP_INVOKE_SUPER_RANGE_nsm:
8805    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8806    b       common_errNoSuchMethod
8807
8808
8809/* continuation for OP_INVOKE_DIRECT_RANGE */
8810
8811    /*
8812     * On entry:
8813     *  r1 = reference (BBBB or CCCC)
8814     *  r10 = "this" register
8815     */
8816.LOP_INVOKE_DIRECT_RANGE_resolve:
8817    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8818    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8819    mov     r2, #METHOD_DIRECT          @ resolver method type
8820    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8821    cmp     r0, #0                      @ got null?
8822    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8823    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8824    b       common_exceptionThrown      @ yes, handle exception
8825
8826
8827/* continuation for OP_FLOAT_TO_LONG */
8828/*
8829 * Convert the float in r0 to a long in r0/r1.
8830 *
8831 * We have to clip values to long min/max per the specification.  The
8832 * expected common case is a "reasonable" value that converts directly
8833 * to modest integer.  The EABI convert function isn't doing this for us.
8834 */
8835f2l_doconv:
8836    stmfd   sp!, {r4, lr}
8837    mov     r1, #0x5f000000             @ (float)maxlong
8838    mov     r4, r0
8839    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8840    cmp     r0, #0                      @ nonzero == yes
8841    mvnne   r0, #0                      @ return maxlong (7fffffff)
8842    mvnne   r1, #0x80000000
8843    ldmnefd sp!, {r4, pc}
8844
8845    mov     r0, r4                      @ recover arg
8846    mov     r1, #0xdf000000             @ (float)minlong
8847    bl      __aeabi_fcmple              @ is arg <= minlong?
8848    cmp     r0, #0                      @ nonzero == yes
8849    movne   r0, #0                      @ return minlong (80000000)
8850    movne   r1, #0x80000000
8851    ldmnefd sp!, {r4, pc}
8852
8853    mov     r0, r4                      @ recover arg
8854    mov     r1, r4
8855    bl      __aeabi_fcmpeq              @ is arg == self?
8856    cmp     r0, #0                      @ zero == no
8857    moveq   r1, #0                      @ return zero for NaN
8858    ldmeqfd sp!, {r4, pc}
8859
8860    mov     r0, r4                      @ recover arg
8861    bl      __aeabi_f2lz                @ convert float to long
8862    ldmfd   sp!, {r4, pc}
8863
8864
8865/* continuation for OP_DOUBLE_TO_LONG */
8866/*
8867 * Convert the double in r0/r1 to a long in r0/r1.
8868 *
8869 * We have to clip values to long min/max per the specification.  The
8870 * expected common case is a "reasonable" value that converts directly
8871 * to modest integer.  The EABI convert function isn't doing this for us.
8872 */
8873d2l_doconv:
8874    stmfd   sp!, {r4, r5, lr}           @ save regs
8875    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8876    add     r3, #0x00e00000             @  0x43e00000
8877    mov     r2, #0                      @ maxlong, as a double (low word)
8878    sub     sp, sp, #4                  @ align for EABI
8879    mov     r4, r0                      @ save a copy of r0
8880    mov     r5, r1                      @  and r1
8881    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8882    cmp     r0, #0                      @ nonzero == yes
8883    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8884    mvnne   r1, #0x80000000
8885    bne     1f
8886
8887    mov     r0, r4                      @ recover arg
8888    mov     r1, r5
8889    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8890    add     r3, #0x00e00000             @  0xc3e00000
8891    mov     r2, #0                      @ minlong, as a double (low word)
8892    bl      __aeabi_dcmple              @ is arg <= minlong?
8893    cmp     r0, #0                      @ nonzero == yes
8894    movne   r0, #0                      @ return minlong (8000000000000000)
8895    movne   r1, #0x80000000
8896    bne     1f
8897
8898    mov     r0, r4                      @ recover arg
8899    mov     r1, r5
8900    mov     r2, r4                      @ compare against self
8901    mov     r3, r5
8902    bl      __aeabi_dcmpeq              @ is arg == self?
8903    cmp     r0, #0                      @ zero == no
8904    moveq   r1, #0                      @ return zero for NaN
8905    beq     1f
8906
8907    mov     r0, r4                      @ recover arg
8908    mov     r1, r5
8909    bl      __aeabi_d2lz                @ convert double to long
8910
89111:
8912    add     sp, sp, #4
8913    ldmfd   sp!, {r4, r5, pc}
8914
8915
8916/* continuation for OP_MUL_LONG */
8917
8918.LOP_MUL_LONG_finish:
8919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8920    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8921    GOTO_OPCODE(ip)                     @ jump to next instruction
8922
8923
8924/* continuation for OP_SHL_LONG */
8925
8926.LOP_SHL_LONG_finish:
8927    mov     r0, r0, asl r2              @  r0<- r0 << r2
8928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8929    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8930    GOTO_OPCODE(ip)                     @ jump to next instruction
8931
8932
8933/* continuation for OP_SHR_LONG */
8934
8935.LOP_SHR_LONG_finish:
8936    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8938    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8939    GOTO_OPCODE(ip)                     @ jump to next instruction
8940
8941
8942/* continuation for OP_USHR_LONG */
8943
8944.LOP_USHR_LONG_finish:
8945    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8947    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8948    GOTO_OPCODE(ip)                     @ jump to next instruction
8949
8950
8951/* continuation for OP_SHL_LONG_2ADDR */
8952
8953.LOP_SHL_LONG_2ADDR_finish:
8954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8955    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8956    GOTO_OPCODE(ip)                     @ jump to next instruction
8957
8958
8959/* continuation for OP_SHR_LONG_2ADDR */
8960
8961.LOP_SHR_LONG_2ADDR_finish:
8962    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8963    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8964    GOTO_OPCODE(ip)                     @ jump to next instruction
8965
8966
8967/* continuation for OP_USHR_LONG_2ADDR */
8968
8969.LOP_USHR_LONG_2ADDR_finish:
8970    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8971    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8972    GOTO_OPCODE(ip)                     @ jump to next instruction
8973
8974
8975/* continuation for OP_EXECUTE_INLINE */
8976
8977    /*
8978     * Extract args, call function.
8979     *  r0 = #of args (0-4)
8980     *  r10 = call index
8981     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8982     *
8983     * Other ideas:
8984     * - Use a jump table from the main piece to jump directly into the
8985     *   AND/LDR pairs.  Costs a data load, saves a branch.
8986     * - Have five separate pieces that do the loading, so we can work the
8987     *   interleave a little better.  Increases code size.
8988     */
8989.LOP_EXECUTE_INLINE_continue:
8990    rsb     r0, r0, #4                  @ r0<- 4-r0
8991    FETCH(r9, 2)                        @ r9<- FEDC
8992    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8993    bl      common_abort                @ (skipped due to ARM prefetch)
89944:  and     ip, r9, #0xf000             @ isolate F
8995    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89963:  and     ip, r9, #0x0f00             @ isolate E
8997    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89982:  and     ip, r9, #0x00f0             @ isolate D
8999    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
90001:  and     ip, r9, #0x000f             @ isolate C
9001    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
90020:
9003    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9004    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9005    @ (not reached)
9006
9007.LOP_EXECUTE_INLINE_table:
9008    .word   gDvmInlineOpsTable
9009
9010
9011/* continuation for OP_EXECUTE_INLINE_RANGE */
9012
9013    /*
9014     * Extract args, call function.
9015     *  r0 = #of args (0-4)
9016     *  r10 = call index
9017     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9018     */
9019.LOP_EXECUTE_INLINE_RANGE_continue:
9020    rsb     r0, r0, #4                  @ r0<- 4-r0
9021    FETCH(r9, 2)                        @ r9<- CCCC
9022    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9023    bl      common_abort                @ (skipped due to ARM prefetch)
90244:  add     ip, r9, #3                  @ base+3
9025    GET_VREG(r3, ip)                    @ r3<- vBase[3]
90263:  add     ip, r9, #2                  @ base+2
9027    GET_VREG(r2, ip)                    @ r2<- vBase[2]
90282:  add     ip, r9, #1                  @ base+1
9029    GET_VREG(r1, ip)                    @ r1<- vBase[1]
90301:  add     ip, r9, #0                  @ (nop)
9031    GET_VREG(r0, ip)                    @ r0<- vBase[0]
90320:
9033    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9034    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9035    @ (not reached)
9036
9037.LOP_EXECUTE_INLINE_RANGE_table:
9038    .word   gDvmInlineOpsTable
9039
9040
9041    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9042    .global dvmAsmSisterEnd
9043dvmAsmSisterEnd:
9044
9045/* File: armv5te/footer.S */
9046
9047/*
9048 * ===========================================================================
9049 *  Common subroutines and data
9050 * ===========================================================================
9051 */
9052
9053
9054
9055    .text
9056    .align  2
9057
9058#if defined(WITH_JIT)
9059#if defined(WITH_SELF_VERIFICATION)
9060    .global dvmJitToInterpPunt
9061dvmJitToInterpPunt:
9062    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9063    b      dvmJitSelfVerificationEnd    @ doesn't return
9064
9065    .global dvmJitToInterpSingleStep
9066dvmJitToInterpSingleStep:
9067    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9068    b      dvmJitSelfVerificationEnd    @ doesn't return
9069
9070    .global dvmJitToTraceSelect
9071dvmJitToTraceSelect:
9072    ldr    r0,[lr, #-1]                 @ pass our target PC
9073    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9074    b      dvmJitSelfVerificationEnd    @ doesn't return
9075
9076    .global dvmJitToBackwardBranch
9077dvmJitToBackwardBranch:
9078    ldr    r0,[lr, #-1]                 @ pass our target PC
9079    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9080    b      dvmJitSelfVerificationEnd    @ doesn't return
9081
9082    .global dvmJitToInterpNormal
9083dvmJitToInterpNormal:
9084    ldr    r0,[lr, #-1]                 @ pass our target PC
9085    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9086    b      dvmJitSelfVerificationEnd    @ doesn't return
9087
9088    .global dvmJitToInterpNoChain
9089dvmJitToInterpNoChain:
9090    mov    r0,rPC                       @ pass our target PC
9091    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9092    b      dvmJitSelfVerificationEnd    @ doesn't return
9093#else
9094/*
9095 * Return from the translation cache to the interpreter when the compiler is
9096 * having issues translating/executing a Dalvik instruction. We have to skip
9097 * the code cache lookup otherwise it is possible to indefinitely bouce
9098 * between the interpreter and the code cache if the instruction that fails
9099 * to be compiled happens to be at a trace start.
9100 */
9101    .global dvmJitToInterpPunt
9102dvmJitToInterpPunt:
9103    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9104    mov    rPC, r0
9105#ifdef EXIT_STATS
9106    mov    r0,lr
9107    bl     dvmBumpPunt;
9108#endif
9109    EXPORT_PC()
9110    mov    r0, #0
9111    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9112    adrl   rIBASE, dvmAsmInstructionStart
9113    FETCH_INST()
9114    GET_INST_OPCODE(ip)
9115    GOTO_OPCODE(ip)
9116
9117/*
9118 * Return to the interpreter to handle a single instruction.
9119 * On entry:
9120 *    r0 <= PC
9121 *    r1 <= PC of resume instruction
9122 *    lr <= resume point in translation
9123 */
9124    .global dvmJitToInterpSingleStep
9125dvmJitToInterpSingleStep:
9126    str    lr,[rGLUE,#offGlue_jitResume]
9127    str    r1,[rGLUE,#offGlue_jitResumePC]
9128    mov    r1,#kInterpEntryInstr
9129    @ enum is 4 byte in aapcs-EABI
9130    str    r1, [rGLUE, #offGlue_entryPoint]
9131    mov    rPC,r0
9132    EXPORT_PC()
9133
9134    adrl   rIBASE, dvmAsmInstructionStart
9135    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9136    str    r2,[rGLUE,#offGlue_jitState]
9137    mov    r1,#1                  @ set changeInterp to bail to debug interp
9138    b      common_gotoBail
9139
9140
9141/*
9142 * Return from the translation cache and immediately request
9143 * a translation for the exit target.  Commonly used following
9144 * invokes.
9145 */
9146    .global dvmJitToTraceSelect
9147dvmJitToTraceSelect:
9148    ldr    rPC,[lr, #-1]           @ get our target PC
9149    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9150    add    rINST,lr,#-5            @ save start of chain branch
9151    mov    r0,rPC
9152    bl     dvmJitGetCodeAddr       @ Is there a translation?
9153    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9154    cmp    r0,#0
9155    beq    2f
9156    mov    r1,rINST
9157    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9158    mov    r1, rPC                  @ arg1 of translation may need this
9159    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9160    cmp    r0,#0                    @ successful chain?
9161    bxne   r0                       @ continue native execution
9162    b      toInterpreter            @ didn't chain - resume with interpreter
9163
9164/* No translation, so request one if profiling isn't disabled*/
91652:
9166    adrl   rIBASE, dvmAsmInstructionStart
9167    GET_JIT_PROF_TABLE(r0)
9168    FETCH_INST()
9169    cmp    r0, #0
9170    bne    common_selectTrace
9171    GET_INST_OPCODE(ip)
9172    GOTO_OPCODE(ip)
9173
9174/*
9175 * Return from the translation cache to the interpreter.
9176 * The return was done with a BLX from thumb mode, and
9177 * the following 32-bit word contains the target rPC value.
9178 * Note that lr (r14) will have its low-order bit set to denote
9179 * its thumb-mode origin.
9180 *
9181 * We'll need to stash our lr origin away, recover the new
9182 * target and then check to see if there is a translation available
9183 * for our new target.  If so, we do a translation chain and
9184 * go back to native execution.  Otherwise, it's back to the
9185 * interpreter (after treating this entry as a potential
9186 * trace start).
9187 */
9188    .global dvmJitToInterpNormal
9189dvmJitToInterpNormal:
9190    ldr    rPC,[lr, #-1]           @ get our target PC
9191    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9192    add    rINST,lr,#-5            @ save start of chain branch
9193#ifdef EXIT_STATS
9194    bl     dvmBumpNormal
9195#endif
9196    mov    r0,rPC
9197    bl     dvmJitGetCodeAddr        @ Is there a translation?
9198    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9199    cmp    r0,#0
9200    beq    toInterpreter            @ go if not, otherwise do chain
9201    mov    r1,rINST
9202    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9203    mov    r1, rPC                  @ arg1 of translation may need this
9204    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9205    cmp    r0,#0                    @ successful chain?
9206    bxne   r0                       @ continue native execution
9207    b      toInterpreter            @ didn't chain - resume with interpreter
9208
9209/*
9210 * Return from the translation cache to the interpreter to do method invocation.
9211 * Check if translation exists for the callee, but don't chain to it.
9212 */
9213    .global dvmJitToInterpNoChain
9214dvmJitToInterpNoChain:
9215#ifdef EXIT_STATS
9216    bl     dvmBumpNoChain
9217#endif
9218    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9219    mov    r0,rPC
9220    bl     dvmJitGetCodeAddr        @ Is there a translation?
9221    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9222    mov    r1, rPC                  @ arg1 of translation may need this
9223    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9224    cmp    r0,#0
9225    bxne   r0                       @ continue native execution if so
9226#endif
9227
9228/*
9229 * No translation, restore interpreter regs and start interpreting.
9230 * rGLUE & rFP were preserved in the translated code, and rPC has
9231 * already been restored by the time we get here.  We'll need to set
9232 * up rIBASE & rINST, and load the address of the JitTable into r0.
9233 */
9234toInterpreter:
9235    EXPORT_PC()
9236    adrl   rIBASE, dvmAsmInstructionStart
9237    FETCH_INST()
9238    GET_JIT_PROF_TABLE(r0)
9239    @ NOTE: intended fallthrough
9240/*
9241 * Common code to update potential trace start counter, and initiate
9242 * a trace-build if appropriate.  On entry, rPC should point to the
9243 * next instruction to execute, and rINST should be already loaded with
9244 * the next opcode word, and r0 holds a pointer to the jit profile
9245 * table (pJitProfTable).
9246 */
9247common_testUpdateProfile:
9248    cmp     r0,#0
9249    GET_INST_OPCODE(ip)
9250    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9251
9252common_updateProfile:
9253    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9254    lsl     r3,r3,#21          @ shift out excess 2047
9255    ldrb    r1,[r0,r3,lsr #21] @ get counter
9256    GET_INST_OPCODE(ip)
9257    subs    r1,r1,#1           @ decrement counter
9258    strb    r1,[r0,r3,lsr #21] @ and store it
9259    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9260
9261/*
9262 * Here, we switch to the debug interpreter to request
9263 * trace selection.  First, though, check to see if there
9264 * is already a native translation in place (and, if so,
9265 * jump to it now).
9266 */
9267    GET_JIT_THRESHOLD(r1)
9268    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9269    strb    r1,[r0,r3,lsr #21] @ reset counter
9270    EXPORT_PC()
9271    mov     r0,rPC
9272    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9273    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9274    mov     r1, rPC                     @ arg1 of translation may need this
9275    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9276    cmp     r0,#0
9277#if !defined(WITH_SELF_VERIFICATION)
9278    bxne    r0                          @ jump to the translation
9279#else
9280    beq     common_selectTrace
9281    /*
9282     * At this point, we have a target translation.  However, if
9283     * that translation is actually the interpret-only pseudo-translation
9284     * we want to treat it the same as no translation.
9285     */
9286    mov     r10, r0                      @ save target
9287    bl      dvmCompilerGetInterpretTemplate
9288    cmp     r0, r10                      @ special case?
9289    bne     dvmJitSelfVerificationStart  @ set up self verification
9290    GET_INST_OPCODE(ip)
9291    GOTO_OPCODE(ip)
9292    /* no return */
9293#endif
9294
9295common_selectTrace:
9296    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9297    str     r2,[rGLUE,#offGlue_jitState]
9298    mov     r2,#kInterpEntryInstr       @ normal entry reason
9299    str     r2,[rGLUE,#offGlue_entryPoint]
9300    mov     r1,#1                       @ set changeInterp
9301    b       common_gotoBail
9302
9303#if defined(WITH_SELF_VERIFICATION)
9304/*
9305 * Save PC and registers to shadow memory for self verification mode
9306 * before jumping to native translation.
9307 * On entry, r10 contains the address of the target translation.
9308 */
9309dvmJitSelfVerificationStart:
9310    mov     r0,rPC                      @ r0<- program counter
9311    mov     r1,rFP                      @ r1<- frame pointer
9312    mov     r2,rGLUE                    @ r2<- InterpState pointer
9313    mov     r3,r10                      @ r3<- target translation
9314    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9315    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9316    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9317    bx      r10                         @ jump to the translation
9318
9319/*
9320 * Restore PC, registers, and interpState to original values
9321 * before jumping back to the interpreter.
9322 */
9323dvmJitSelfVerificationEnd:
9324    mov    r1,rFP                        @ pass ending fp
9325    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9326    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9327    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9328    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9329    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9330    cmp    r1,#0                         @ check for punt condition
9331    beq    1f
9332    mov    r2,#kJitSelfVerification      @ ask for self verification
9333    str    r2,[rGLUE,#offGlue_jitState]
9334    mov    r2,#kInterpEntryInstr         @ normal entry reason
9335    str    r2,[rGLUE,#offGlue_entryPoint]
9336    mov    r1,#1                         @ set changeInterp
9337    b      common_gotoBail
9338
93391:                                       @ exit to interpreter without check
9340    EXPORT_PC()
9341    adrl   rIBASE, dvmAsmInstructionStart
9342    FETCH_INST()
9343    GET_INST_OPCODE(ip)
9344    GOTO_OPCODE(ip)
9345#endif
9346
9347#endif
9348
9349/*
9350 * Common code when a backward branch is taken.
9351 *
9352 * On entry:
9353 *  r9 is PC adjustment *in bytes*
9354 */
9355common_backwardBranch:
9356    mov     r0, #kInterpEntryInstr
9357    bl      common_periodicChecks
9358#if defined(WITH_JIT)
9359    GET_JIT_PROF_TABLE(r0)
9360    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9361    cmp     r0,#0
9362    bne     common_updateProfile
9363    GET_INST_OPCODE(ip)
9364    GOTO_OPCODE(ip)
9365#else
9366    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9368    GOTO_OPCODE(ip)                     @ jump to next instruction
9369#endif
9370
9371
9372/*
9373 * Need to see if the thread needs to be suspended or debugger/profiler
9374 * activity has begun.
9375 *
9376 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9377 * have to do the second ldr.
9378 *
9379 * TODO: reduce this so we're just checking a single location.
9380 *
9381 * On entry:
9382 *  r0 is reentry type, e.g. kInterpEntryInstr
9383 *  r9 is trampoline PC adjustment *in bytes*
9384 */
9385common_periodicChecks:
9386    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9387
9388    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9389    str     r0, [rGLUE, #offGlue_entryPoint]
9390
9391#if defined(WITH_DEBUGGER)
9392    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9393#endif
9394#if defined(WITH_PROFILER)
9395    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9396#endif
9397
9398    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9399
9400#if defined(WITH_DEBUGGER)
9401    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9402#endif
9403#if defined (WITH_PROFILER)
9404    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9405#endif
9406
9407    cmp     r3, #0                      @ suspend pending?
9408    bne     2f                          @ yes, do full suspension check
9409
9410#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9411# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9412    orrs    r1, r1, r2                  @ r1<- r1 | r2
9413    cmp     r1, #0                      @ debugger attached or profiler started?
9414# elif defined(WITH_DEBUGGER)
9415    cmp     r1, #0                      @ debugger attached?
9416# elif defined(WITH_PROFILER)
9417    cmp     r2, #0                      @ profiler started?
9418# endif
9419    bne     3f                          @ debugger/profiler, switch interp
9420#endif
9421
9422    bx      lr                          @ nothing to do, return
9423
94242:  @ check suspend
9425    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9426    EXPORT_PC()                         @ need for precise GC
9427    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9428
94293:  @ debugger/profiler enabled, bail out
9430    add     rPC, rPC, r9                @ update rPC
9431    mov     r1, #1                      @ "want switch" = true
9432    b       common_gotoBail
9433
9434
9435/*
9436 * The equivalent of "goto bail", this calls through the "bail handler".
9437 *
9438 * State registers will be saved to the "glue" area before bailing.
9439 *
9440 * On entry:
9441 *  r1 is "bool changeInterp", indicating if we want to switch to the
9442 *     other interpreter or just bail all the way out
9443 */
9444common_gotoBail:
9445    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9446    mov     r0, rGLUE                   @ r0<- glue ptr
9447    b       dvmMterpStdBail             @ call(glue, changeInterp)
9448
9449    @add     r1, r1, #1                  @ using (boolean+1)
9450    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9451    @bl      _longjmp                    @ does not return
9452    @bl      common_abort
9453
9454
9455/*
9456 * Common code for method invocation with range.
9457 *
9458 * On entry:
9459 *  r0 is "Method* methodToCall", the method we're trying to call
9460 */
9461common_invokeMethodRange:
9462.LinvokeNewRange:
9463    @ prepare to copy args to "outs" area of current frame
9464    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9465    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9466    beq     .LinvokeArgsDone            @ if no args, skip the rest
9467    FETCH(r1, 2)                        @ r1<- CCCC
9468
9469    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9470    @ (very few methods have > 10 args; could unroll for common cases)
9471    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9472    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9473    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94741:  ldr     r1, [r3], #4                @ val = *fp++
9475    subs    r2, r2, #1                  @ count--
9476    str     r1, [r10], #4               @ *outs++ = val
9477    bne     1b                          @ ...while count != 0
9478    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9479    b       .LinvokeArgsDone
9480
9481/*
9482 * Common code for method invocation without range.
9483 *
9484 * On entry:
9485 *  r0 is "Method* methodToCall", the method we're trying to call
9486 */
9487common_invokeMethodNoRange:
9488.LinvokeNewNoRange:
9489    @ prepare to copy args to "outs" area of current frame
9490    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9491    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9492    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9493    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9494    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9495    beq     .LinvokeArgsDone
9496
9497    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9498.LinvokeNonRange:
9499    rsb     r2, r2, #5                  @ r2<- 5-r2
9500    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9501    bl      common_abort                @ (skipped due to ARM prefetch)
95025:  and     ip, rINST, #0x0f00          @ isolate A
9503    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9504    mov     r0, r0                      @ nop
9505    str     r2, [r10, #-4]!             @ *--outs = vA
95064:  and     ip, r1, #0xf000             @ isolate G
9507    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9508    mov     r0, r0                      @ nop
9509    str     r2, [r10, #-4]!             @ *--outs = vG
95103:  and     ip, r1, #0x0f00             @ isolate F
9511    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9512    mov     r0, r0                      @ nop
9513    str     r2, [r10, #-4]!             @ *--outs = vF
95142:  and     ip, r1, #0x00f0             @ isolate E
9515    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9516    mov     r0, r0                      @ nop
9517    str     r2, [r10, #-4]!             @ *--outs = vE
95181:  and     ip, r1, #0x000f             @ isolate D
9519    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9520    mov     r0, r0                      @ nop
9521    str     r2, [r10, #-4]!             @ *--outs = vD
95220:  @ fall through to .LinvokeArgsDone
9523
9524.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9525    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9526    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9527    @ find space for the new stack frame, check for overflow
9528    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9529    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9530    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9531@    bl      common_dumpRegs
9532    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9533    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9534    cmp     r3, r9                      @ bottom < interpStackEnd?
9535    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9536    blt     .LstackOverflow             @ yes, this frame will overflow stack
9537
9538    @ set up newSaveArea
9539#ifdef EASY_GDB
9540    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9541    str     ip, [r10, #offStackSaveArea_prevSave]
9542#endif
9543    str     rFP, [r10, #offStackSaveArea_prevFrame]
9544    str     rPC, [r10, #offStackSaveArea_savedPc]
9545#if defined(WITH_JIT)
9546    mov     r9, #0
9547    str     r9, [r10, #offStackSaveArea_returnAddr]
9548#endif
9549    str     r0, [r10, #offStackSaveArea_method]
9550    tst     r3, #ACC_NATIVE
9551    bne     .LinvokeNative
9552
9553    /*
9554    stmfd   sp!, {r0-r3}
9555    bl      common_printNewline
9556    mov     r0, rFP
9557    mov     r1, #0
9558    bl      dvmDumpFp
9559    ldmfd   sp!, {r0-r3}
9560    stmfd   sp!, {r0-r3}
9561    mov     r0, r1
9562    mov     r1, r10
9563    bl      dvmDumpFp
9564    bl      common_printNewline
9565    ldmfd   sp!, {r0-r3}
9566    */
9567
9568    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9569    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9570    mov     rPC, r2                         @ publish new rPC
9571    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9572
9573    @ Update "glue" values for the new method
9574    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9575    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9576    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9577#if defined(WITH_JIT)
9578    GET_JIT_PROF_TABLE(r0)
9579    mov     rFP, r1                         @ fp = newFp
9580    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9581    mov     rINST, r9                       @ publish new rINST
9582    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9583    cmp     r0,#0
9584    bne     common_updateProfile
9585    GOTO_OPCODE(ip)                         @ jump to next instruction
9586#else
9587    mov     rFP, r1                         @ fp = newFp
9588    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9589    mov     rINST, r9                       @ publish new rINST
9590    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9591    GOTO_OPCODE(ip)                         @ jump to next instruction
9592#endif
9593
9594.LinvokeNative:
9595    @ Prep for the native call
9596    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9597    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9598    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9599    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9600    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9601    mov     r9, r3                      @ r9<- glue->self (preserve)
9602
9603    mov     r2, r0                      @ r2<- methodToCall
9604    mov     r0, r1                      @ r0<- newFp (points to args)
9605    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9606
9607#ifdef ASSIST_DEBUGGER
9608    /* insert fake function header to help gdb find the stack frame */
9609    b       .Lskip
9610    .type   dalvik_mterp, %function
9611dalvik_mterp:
9612    .fnstart
9613    MTERP_ENTRY1
9614    MTERP_ENTRY2
9615.Lskip:
9616#endif
9617
9618    @mov     lr, pc                      @ set return addr
9619    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9620    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9621
9622    @ native return; r9=self, r10=newSaveArea
9623    @ equivalent to dvmPopJniLocals
9624    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9625    ldr     r1, [r9, #offThread_exception] @ check for exception
9626    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9627    cmp     r1, #0                      @ null?
9628    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9629    bne     common_exceptionThrown      @ no, handle exception
9630
9631    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9632    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9633    GOTO_OPCODE(ip)                     @ jump to next instruction
9634
9635.LstackOverflow:    @ r0=methodToCall
9636    mov     r1, r0                      @ r1<- methodToCall
9637    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9638    bl      dvmHandleStackOverflow
9639    b       common_exceptionThrown
9640#ifdef ASSIST_DEBUGGER
9641    .fnend
9642#endif
9643
9644
9645    /*
9646     * Common code for method invocation, calling through "glue code".
9647     *
9648     * TODO: now that we have range and non-range invoke handlers, this
9649     *       needs to be split into two.  Maybe just create entry points
9650     *       that set r9 and jump here?
9651     *
9652     * On entry:
9653     *  r0 is "Method* methodToCall", the method we're trying to call
9654     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9655     */
9656     .if    0
9657.LinvokeOld:
9658    sub     sp, sp, #8                  @ space for args + pad
9659    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9660    mov     r2, r0                      @ A2<- methodToCall
9661    mov     r0, rGLUE                   @ A0<- glue
9662    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9663    mov     r1, r9                      @ A1<- methodCallRange
9664    mov     r3, rINST, lsr #8           @ A3<- AA
9665    str     ip, [sp, #0]                @ A4<- ip
9666    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9667    add     sp, sp, #8                  @ remove arg area
9668    b       common_resumeAfterGlueCall  @ continue to next instruction
9669    .endif
9670
9671
9672
9673/*
9674 * Common code for handling a return instruction.
9675 *
9676 * This does not return.
9677 */
9678common_returnFromMethod:
9679.LreturnNew:
9680    mov     r0, #kInterpEntryReturn
9681    mov     r9, #0
9682    bl      common_periodicChecks
9683
9684    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9685    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9686    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9687    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9688                                        @ r2<- method we're returning to
9689    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9690    cmp     r2, #0                      @ is this a break frame?
9691    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9692    mov     r1, #0                      @ "want switch" = false
9693    beq     common_gotoBail             @ break frame, bail out completely
9694
9695    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9696    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9697    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9698    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9699#if defined(WITH_JIT)
9700    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
9701    GET_JIT_PROF_TABLE(r0)
9702    mov     rPC, r9                     @ publish new rPC
9703    str     r1, [rGLUE, #offGlue_methodClassDex]
9704    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
9705    cmp     r10, #0                      @ caller is compiled code
9706    blxne   r10
9707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9708    cmp     r0,#0
9709    bne     common_updateProfile
9710    GOTO_OPCODE(ip)                     @ jump to next instruction
9711#else
9712    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9713    mov     rPC, r9                     @ publish new rPC
9714    str     r1, [rGLUE, #offGlue_methodClassDex]
9715    GOTO_OPCODE(ip)                     @ jump to next instruction
9716#endif
9717
9718    /*
9719     * Return handling, calls through "glue code".
9720     */
9721     .if    0
9722.LreturnOld:
9723    SAVE_PC_FP_TO_GLUE()                @ export state
9724    mov     r0, rGLUE                   @ arg to function
9725    bl      dvmMterp_returnFromMethod
9726    b       common_resumeAfterGlueCall
9727    .endif
9728
9729
9730/*
9731 * Somebody has thrown an exception.  Handle it.
9732 *
9733 * If the exception processing code returns to us (instead of falling
9734 * out of the interpreter), continue with whatever the next instruction
9735 * now happens to be.
9736 *
9737 * This does not return.
9738 */
9739     .global dvmMterpCommonExceptionThrown
9740dvmMterpCommonExceptionThrown:
9741common_exceptionThrown:
9742.LexceptionNew:
9743    mov     r0, #kInterpEntryThrow
9744    mov     r9, #0
9745    bl      common_periodicChecks
9746
9747#if defined(WITH_JIT)
9748    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9749    str     r2,[rGLUE,#offGlue_jitState]
9750#endif
9751
9752    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9753    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9754    mov     r1, r10                     @ r1<- self
9755    mov     r0, r9                      @ r0<- exception
9756    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9757    mov     r3, #0                      @ r3<- NULL
9758    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9759
9760    /* set up args and a local for "&fp" */
9761    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9762    str     rFP, [sp, #-4]!             @ *--sp = fp
9763    mov     ip, sp                      @ ip<- &fp
9764    mov     r3, #0                      @ r3<- false
9765    str     ip, [sp, #-4]!              @ *--sp = &fp
9766    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9767    mov     r0, r10                     @ r0<- self
9768    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9769    mov     r2, r9                      @ r2<- exception
9770    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9771    mov     r1, r1, asr #1              @ r1<- offset in code units
9772
9773    /* call, r0 gets catchRelPc (a code-unit offset) */
9774    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9775
9776    /* fix earlier stack overflow if necessary; may trash rFP */
9777    ldrb    r1, [r10, #offThread_stackOverflowed]
9778    cmp     r1, #0                      @ did we overflow earlier?
9779    beq     1f                          @ no, skip ahead
9780    mov     rFP, r0                     @ save relPc result in rFP
9781    mov     r0, r10                     @ r0<- self
9782    bl      dvmCleanupStackOverflow     @ call(self)
9783    mov     r0, rFP                     @ restore result
97841:
9785
9786    /* update frame pointer and check result from dvmFindCatchBlock */
9787    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9788    cmp     r0, #0                      @ is catchRelPc < 0?
9789    add     sp, sp, #8                  @ restore stack
9790    bmi     .LnotCaughtLocally
9791
9792    /* adjust locals to match self->curFrame and updated PC */
9793    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9794    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9795    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9796    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9797    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9798    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9799    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9800    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9801
9802    /* release the tracked alloc on the exception */
9803    mov     r0, r9                      @ r0<- exception
9804    mov     r1, r10                     @ r1<- self
9805    bl      dvmReleaseTrackedAlloc      @ release the exception
9806
9807    /* restore the exception if the handler wants it */
9808    FETCH_INST()                        @ load rINST from rPC
9809    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9810    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9811    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9812    GOTO_OPCODE(ip)                     @ jump to next instruction
9813
9814.LnotCaughtLocally: @ r9=exception, r10=self
9815    /* fix stack overflow if necessary */
9816    ldrb    r1, [r10, #offThread_stackOverflowed]
9817    cmp     r1, #0                      @ did we overflow earlier?
9818    movne   r0, r10                     @ if yes: r0<- self
9819    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9820
9821    @ may want to show "not caught locally" debug messages here
9822#if DVM_SHOW_EXCEPTION >= 2
9823    /* call __android_log_print(prio, tag, format, ...) */
9824    /* "Exception %s from %s:%d not caught locally" */
9825    @ dvmLineNumFromPC(method, pc - method->insns)
9826    ldr     r0, [rGLUE, #offGlue_method]
9827    ldr     r1, [r0, #offMethod_insns]
9828    sub     r1, rPC, r1
9829    asr     r1, r1, #1
9830    bl      dvmLineNumFromPC
9831    str     r0, [sp, #-4]!
9832    @ dvmGetMethodSourceFile(method)
9833    ldr     r0, [rGLUE, #offGlue_method]
9834    bl      dvmGetMethodSourceFile
9835    str     r0, [sp, #-4]!
9836    @ exception->clazz->descriptor
9837    ldr     r3, [r9, #offObject_clazz]
9838    ldr     r3, [r3, #offClassObject_descriptor]
9839    @
9840    ldr     r2, strExceptionNotCaughtLocally
9841    ldr     r1, strLogTag
9842    mov     r0, #3                      @ LOG_DEBUG
9843    bl      __android_log_print
9844#endif
9845    str     r9, [r10, #offThread_exception] @ restore exception
9846    mov     r0, r9                      @ r0<- exception
9847    mov     r1, r10                     @ r1<- self
9848    bl      dvmReleaseTrackedAlloc      @ release the exception
9849    mov     r1, #0                      @ "want switch" = false
9850    b       common_gotoBail             @ bail out
9851
9852
9853    /*
9854     * Exception handling, calls through "glue code".
9855     */
9856    .if     0
9857.LexceptionOld:
9858    SAVE_PC_FP_TO_GLUE()                @ export state
9859    mov     r0, rGLUE                   @ arg to function
9860    bl      dvmMterp_exceptionThrown
9861    b       common_resumeAfterGlueCall
9862    .endif
9863
9864
9865/*
9866 * After returning from a "glued" function, pull out the updated
9867 * values and start executing at the next instruction.
9868 */
9869common_resumeAfterGlueCall:
9870    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9871    FETCH_INST()                        @ load rINST from rPC
9872    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9873    GOTO_OPCODE(ip)                     @ jump to next instruction
9874
9875/*
9876 * Invalid array index.
9877 */
9878common_errArrayIndex:
9879    EXPORT_PC()
9880    ldr     r0, strArrayIndexException
9881    mov     r1, #0
9882    bl      dvmThrowException
9883    b       common_exceptionThrown
9884
9885/*
9886 * Invalid array value.
9887 */
9888common_errArrayStore:
9889    EXPORT_PC()
9890    ldr     r0, strArrayStoreException
9891    mov     r1, #0
9892    bl      dvmThrowException
9893    b       common_exceptionThrown
9894
9895/*
9896 * Integer divide or mod by zero.
9897 */
9898common_errDivideByZero:
9899    EXPORT_PC()
9900    ldr     r0, strArithmeticException
9901    ldr     r1, strDivideByZero
9902    bl      dvmThrowException
9903    b       common_exceptionThrown
9904
9905/*
9906 * Attempt to allocate an array with a negative size.
9907 */
9908common_errNegativeArraySize:
9909    EXPORT_PC()
9910    ldr     r0, strNegativeArraySizeException
9911    mov     r1, #0
9912    bl      dvmThrowException
9913    b       common_exceptionThrown
9914
9915/*
9916 * Invocation of a non-existent method.
9917 */
9918common_errNoSuchMethod:
9919    EXPORT_PC()
9920    ldr     r0, strNoSuchMethodError
9921    mov     r1, #0
9922    bl      dvmThrowException
9923    b       common_exceptionThrown
9924
9925/*
9926 * We encountered a null object when we weren't expecting one.  We
9927 * export the PC, throw a NullPointerException, and goto the exception
9928 * processing code.
9929 */
9930common_errNullObject:
9931    EXPORT_PC()
9932    ldr     r0, strNullPointerException
9933    mov     r1, #0
9934    bl      dvmThrowException
9935    b       common_exceptionThrown
9936
9937/*
9938 * For debugging, cause an immediate fault.  The source address will
9939 * be in lr (use a bl instruction to jump here).
9940 */
9941common_abort:
9942    ldr     pc, .LdeadFood
9943.LdeadFood:
9944    .word   0xdeadf00d
9945
9946/*
9947 * Spit out a "we were here", preserving all registers.  (The attempt
9948 * to save ip won't work, but we need to save an even number of
9949 * registers for EABI 64-bit stack alignment.)
9950 */
9951    .macro  SQUEAK num
9952common_squeak\num:
9953    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9954    ldr     r0, strSqueak
9955    mov     r1, #\num
9956    bl      printf
9957    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9958    bx      lr
9959    .endm
9960
9961    SQUEAK  0
9962    SQUEAK  1
9963    SQUEAK  2
9964    SQUEAK  3
9965    SQUEAK  4
9966    SQUEAK  5
9967
9968/*
9969 * Spit out the number in r0, preserving registers.
9970 */
9971common_printNum:
9972    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9973    mov     r1, r0
9974    ldr     r0, strSqueak
9975    bl      printf
9976    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9977    bx      lr
9978
9979/*
9980 * Print a newline, preserving registers.
9981 */
9982common_printNewline:
9983    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9984    ldr     r0, strNewline
9985    bl      printf
9986    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9987    bx      lr
9988
9989    /*
9990     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9991     */
9992common_printHex:
9993    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9994    mov     r1, r0
9995    ldr     r0, strPrintHex
9996    bl      printf
9997    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9998    bx      lr
9999
10000/*
10001 * Print the 64-bit quantity in r0-r1, preserving registers.
10002 */
10003common_printLong:
10004    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10005    mov     r3, r1
10006    mov     r2, r0
10007    ldr     r0, strPrintLong
10008    bl      printf
10009    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10010    bx      lr
10011
10012/*
10013 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10014 */
10015common_printMethod:
10016    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10017    bl      dvmMterpPrintMethod
10018    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10019    bx      lr
10020
10021/*
10022 * Call a C helper function that dumps regs and possibly some
10023 * additional info.  Requires the C function to be compiled in.
10024 */
10025    .if     0
10026common_dumpRegs:
10027    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10028    bl      dvmMterpDumpArmRegs
10029    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10030    bx      lr
10031    .endif
10032
10033#if 0
10034/*
10035 * Experiment on VFP mode.
10036 *
10037 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10038 *
10039 * Updates the bits specified by "mask", setting them to the values in "val".
10040 */
10041setFPSCR:
10042    and     r0, r0, r1                  @ make sure no stray bits are set
10043    fmrx    r2, fpscr                   @ get VFP reg
10044    mvn     r1, r1                      @ bit-invert mask
10045    and     r2, r2, r1                  @ clear masked bits
10046    orr     r2, r2, r0                  @ set specified bits
10047    fmxr    fpscr, r2                   @ set VFP reg
10048    mov     r0, r2                      @ return new value
10049    bx      lr
10050
10051    .align  2
10052    .global dvmConfigureFP
10053    .type   dvmConfigureFP, %function
10054dvmConfigureFP:
10055    stmfd   sp!, {ip, lr}
10056    /* 0x03000000 sets DN/FZ */
10057    /* 0x00009f00 clears the six exception enable flags */
10058    bl      common_squeak0
10059    mov     r0, #0x03000000             @ r0<- 0x03000000
10060    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10061    bl      setFPSCR
10062    ldmfd   sp!, {ip, pc}
10063#endif
10064
10065
10066/*
10067 * String references, must be close to the code that uses them.
10068 */
10069    .align  2
10070strArithmeticException:
10071    .word   .LstrArithmeticException
10072strArrayIndexException:
10073    .word   .LstrArrayIndexException
10074strArrayStoreException:
10075    .word   .LstrArrayStoreException
10076strDivideByZero:
10077    .word   .LstrDivideByZero
10078strNegativeArraySizeException:
10079    .word   .LstrNegativeArraySizeException
10080strNoSuchMethodError:
10081    .word   .LstrNoSuchMethodError
10082strNullPointerException:
10083    .word   .LstrNullPointerException
10084
10085strLogTag:
10086    .word   .LstrLogTag
10087strExceptionNotCaughtLocally:
10088    .word   .LstrExceptionNotCaughtLocally
10089
10090strNewline:
10091    .word   .LstrNewline
10092strSqueak:
10093    .word   .LstrSqueak
10094strPrintHex:
10095    .word   .LstrPrintHex
10096strPrintLong:
10097    .word   .LstrPrintLong
10098
10099/*
10100 * Zero-terminated ASCII string data.
10101 *
10102 * On ARM we have two choices: do like gcc does, and LDR from a .word
10103 * with the address, or use an ADR pseudo-op to get the address
10104 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10105 * PC-relative addressing mode and hence has a limited range, which
10106 * makes it not work well with mergeable string sections.
10107 */
10108    .section .rodata.str1.4,"aMS",%progbits,1
10109
10110.LstrBadEntryPoint:
10111    .asciz  "Bad entry point %d\n"
10112.LstrArithmeticException:
10113    .asciz  "Ljava/lang/ArithmeticException;"
10114.LstrArrayIndexException:
10115    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10116.LstrArrayStoreException:
10117    .asciz  "Ljava/lang/ArrayStoreException;"
10118.LstrClassCastException:
10119    .asciz  "Ljava/lang/ClassCastException;"
10120.LstrDivideByZero:
10121    .asciz  "divide by zero"
10122.LstrFilledNewArrayNotImpl:
10123    .asciz  "filled-new-array only implemented for objects and 'int'"
10124.LstrInternalError:
10125    .asciz  "Ljava/lang/InternalError;"
10126.LstrInstantiationError:
10127    .asciz  "Ljava/lang/InstantiationError;"
10128.LstrNegativeArraySizeException:
10129    .asciz  "Ljava/lang/NegativeArraySizeException;"
10130.LstrNoSuchMethodError:
10131    .asciz  "Ljava/lang/NoSuchMethodError;"
10132.LstrNullPointerException:
10133    .asciz  "Ljava/lang/NullPointerException;"
10134
10135.LstrLogTag:
10136    .asciz  "mterp"
10137.LstrExceptionNotCaughtLocally:
10138    .asciz  "Exception %s from %s:%d not caught locally\n"
10139
10140.LstrNewline:
10141    .asciz  "\n"
10142.LstrSqueak:
10143    .asciz  "<%d>"
10144.LstrPrintHex:
10145    .asciz  "<0x%x>"
10146.LstrPrintLong:
10147    .asciz  "<%lld>"
10148
10149
10150