InterpAsm-armv5te-vfp.S revision a80b76553c2b9f33c4063ae8c69c5362d961de81
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  rIBASE    interpreted instruction base pointer, used for computed goto
67  r8  rINST     first 16-bit code unit of current instruction
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 rIBASE  r7
79#define rINST   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
179/*
180 * Get/set the 32-bit value from a Dalvik register.
181 */
182#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
183#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
184
185/*
186 * Convert a virtual register index into an address.
187 */
188#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
189        add     _reg, rFP, _vreg, lsl #2
190
191/*
192 * This is a #include, not a %include, because we want the C pre-processor
193 * to expand the macros into assembler assignment statements.
194 */
195#include "../common/asm-constants.h"
196
197
198/* File: armv5te/platform.S */
199/*
200 * ===========================================================================
201 *  CPU-version-specific defines
202 * ===========================================================================
203 */
204
205/*
206 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
207 * one-way branch.
208 *
209 * May modify IP.  Does not modify LR.
210 */
211.macro  LDR_PC source
212    ldr     pc, \source
213.endm
214
215/*
216 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
217 * Jump to subroutine.
218 *
219 * May modify IP and LR.
220 */
221.macro  LDR_PC_LR source
222    mov     lr, pc
223    ldr     pc, \source
224.endm
225
226/*
227 * Macro for "LDMFD SP!, {...regs...,PC}".
228 *
229 * May modify IP and LR.
230 */
231.macro  LDMFD_PC regs
232    ldmfd   sp!, {\regs,pc}
233.endm
234
235
236/* File: armv5te/entry.S */
237/*
238 * Copyright (C) 2008 The Android Open Source Project
239 *
240 * Licensed under the Apache License, Version 2.0 (the "License");
241 * you may not use this file except in compliance with the License.
242 * You may obtain a copy of the License at
243 *
244 *      http://www.apache.org/licenses/LICENSE-2.0
245 *
246 * Unless required by applicable law or agreed to in writing, software
247 * distributed under the License is distributed on an "AS IS" BASIS,
248 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
249 * See the License for the specific language governing permissions and
250 * limitations under the License.
251 */
252/*
253 * Interpreter entry point.
254 */
255
256/*
257 * We don't have formal stack frames, so gdb scans upward in the code
258 * to find the start of the function (a label with the %function type),
259 * and then looks at the next few instructions to figure out what
260 * got pushed onto the stack.  From this it figures out how to restore
261 * the registers, including PC, for the previous stack frame.  If gdb
262 * sees a non-function label, it stops scanning, so either we need to
263 * have nothing but assembler-local labels between the entry point and
264 * the break, or we need to fake it out.
265 *
266 * When this is defined, we add some stuff to make gdb less confused.
267 */
268#define ASSIST_DEBUGGER 1
269
270    .text
271    .align  2
272    .global dvmMterpStdRun
273    .type   dvmMterpStdRun, %function
274
275/*
276 * On entry:
277 *  r0  MterpGlue* glue
278 *
279 * This function returns a boolean "changeInterp" value.  The return comes
280 * via a call to dvmMterpStdBail().
281 */
282dvmMterpStdRun:
283#define MTERP_ENTRY1 \
284    .save {r4-r10,fp,lr}; \
285    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
286#define MTERP_ENTRY2 \
287    .pad    #4; \
288    sub     sp, sp, #4                  @ align 64
289
290    .fnstart
291    MTERP_ENTRY1
292    MTERP_ENTRY2
293
294    /* save stack pointer, add magic word for debuggerd */
295    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
296
297    /* set up "named" registers, figure out entry point */
298    mov     rGLUE, r0                   @ set rGLUE
299    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
300    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
301    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
302    cmp     r1, #kInterpEntryInstr      @ usual case?
303    bne     .Lnot_instr                 @ no, handle it
304
305    /* start executing the instruction at rPC */
306    FETCH_INST()                        @ load rINST from rPC
307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
308    GOTO_OPCODE(ip)                     @ jump to next instruction
309
310.Lnot_instr:
311    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
312    beq     common_returnFromMethod
313
314.Lnot_return:
315    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
316    beq     common_exceptionThrown
317
318.Lbad_arg:
319    ldr     r0, strBadEntryPoint
320    @ r1 holds value of entryPoint
321    bl      printf
322    bl      dvmAbort
323    .fnend
324
325
326    .global dvmMterpStdBail
327    .type   dvmMterpStdBail, %function
328
329/*
330 * Restore the stack pointer and PC from the save point established on entry.
331 * This is essentially the same as a longjmp, but should be cheaper.  The
332 * last instruction causes us to return to whoever called dvmMterpStdRun.
333 *
334 * We pushed some registers on the stack in dvmMterpStdRun, then saved
335 * SP and LR.  Here we restore SP, restore the registers, and then restore
336 * LR to PC.
337 *
338 * On entry:
339 *  r0  MterpGlue* glue
340 *  r1  bool changeInterp
341 */
342dvmMterpStdBail:
343    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
344    mov     r0, r1                          @ return the changeInterp value
345    add     sp, sp, #4                      @ un-align 64
346    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
347
348
349/*
350 * String references.
351 */
352strBadEntryPoint:
353    .word   .LstrBadEntryPoint
354
355
356
357    .global dvmAsmInstructionStart
358    .type   dvmAsmInstructionStart, %function
359dvmAsmInstructionStart = .L_OP_NOP
360    .text
361
362/* ------------------------------ */
363    .balign 64
364.L_OP_NOP: /* 0x00 */
365/* File: armv5te/OP_NOP.S */
366    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
367    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
368    GOTO_OPCODE(ip)                     @ execute it
369
370#ifdef ASSIST_DEBUGGER
371    /* insert fake function header to help gdb find the stack frame */
372    .type   dalvik_inst, %function
373dalvik_inst:
374    .fnstart
375    MTERP_ENTRY1
376    MTERP_ENTRY2
377    .fnend
378#endif
379
380
381/* ------------------------------ */
382    .balign 64
383.L_OP_MOVE: /* 0x01 */
384/* File: armv5te/OP_MOVE.S */
385    /* for move, move-object, long-to-int */
386    /* op vA, vB */
387    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
388    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
389    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
390    GET_VREG(r2, r1)                    @ r2<- fp[B]
391    and     r0, r0, #15
392    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
393    SET_VREG(r2, r0)                    @ fp[A]<- r2
394    GOTO_OPCODE(ip)                     @ execute next instruction
395
396
397/* ------------------------------ */
398    .balign 64
399.L_OP_MOVE_FROM16: /* 0x02 */
400/* File: armv5te/OP_MOVE_FROM16.S */
401    /* for: move/from16, move-object/from16 */
402    /* op vAA, vBBBB */
403    FETCH(r1, 1)                        @ r1<- BBBB
404    mov     r0, rINST, lsr #8           @ r0<- AA
405    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
406    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
407    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
408    SET_VREG(r2, r0)                    @ fp[AA]<- r2
409    GOTO_OPCODE(ip)                     @ jump to next instruction
410
411
412/* ------------------------------ */
413    .balign 64
414.L_OP_MOVE_16: /* 0x03 */
415/* File: armv5te/OP_MOVE_16.S */
416    /* for: move/16, move-object/16 */
417    /* op vAAAA, vBBBB */
418    FETCH(r1, 2)                        @ r1<- BBBB
419    FETCH(r0, 1)                        @ r0<- AAAA
420    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
421    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
423    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
424    GOTO_OPCODE(ip)                     @ jump to next instruction
425
426
427/* ------------------------------ */
428    .balign 64
429.L_OP_MOVE_WIDE: /* 0x04 */
430/* File: armv5te/OP_MOVE_WIDE.S */
431    /* move-wide vA, vB */
432    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
433    mov     r2, rINST, lsr #8           @ r2<- A(+)
434    mov     r3, rINST, lsr #12          @ r3<- B
435    and     r2, r2, #15
436    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
437    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
438    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
439    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
441    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
442    GOTO_OPCODE(ip)                     @ jump to next instruction
443
444
445/* ------------------------------ */
446    .balign 64
447.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
448/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
449    /* move-wide/from16 vAA, vBBBB */
450    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
451    FETCH(r3, 1)                        @ r3<- BBBB
452    mov     r2, rINST, lsr #8           @ r2<- AA
453    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
454    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
455    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
456    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
458    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
459    GOTO_OPCODE(ip)                     @ jump to next instruction
460
461
462/* ------------------------------ */
463    .balign 64
464.L_OP_MOVE_WIDE_16: /* 0x06 */
465/* File: armv5te/OP_MOVE_WIDE_16.S */
466    /* move-wide/16 vAAAA, vBBBB */
467    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
468    FETCH(r3, 2)                        @ r3<- BBBB
469    FETCH(r2, 1)                        @ r2<- AAAA
470    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
471    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
472    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
473    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
475    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
476    GOTO_OPCODE(ip)                     @ jump to next instruction
477
478
479/* ------------------------------ */
480    .balign 64
481.L_OP_MOVE_OBJECT: /* 0x07 */
482/* File: armv5te/OP_MOVE_OBJECT.S */
483/* File: armv5te/OP_MOVE.S */
484    /* for move, move-object, long-to-int */
485    /* op vA, vB */
486    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
487    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
488    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
489    GET_VREG(r2, r1)                    @ r2<- fp[B]
490    and     r0, r0, #15
491    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
492    SET_VREG(r2, r0)                    @ fp[A]<- r2
493    GOTO_OPCODE(ip)                     @ execute next instruction
494
495
496
497/* ------------------------------ */
498    .balign 64
499.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
500/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
501/* File: armv5te/OP_MOVE_FROM16.S */
502    /* for: move/from16, move-object/from16 */
503    /* op vAA, vBBBB */
504    FETCH(r1, 1)                        @ r1<- BBBB
505    mov     r0, rINST, lsr #8           @ r0<- AA
506    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
507    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
509    SET_VREG(r2, r0)                    @ fp[AA]<- r2
510    GOTO_OPCODE(ip)                     @ jump to next instruction
511
512
513
514/* ------------------------------ */
515    .balign 64
516.L_OP_MOVE_OBJECT_16: /* 0x09 */
517/* File: armv5te/OP_MOVE_OBJECT_16.S */
518/* File: armv5te/OP_MOVE_16.S */
519    /* for: move/16, move-object/16 */
520    /* op vAAAA, vBBBB */
521    FETCH(r1, 2)                        @ r1<- BBBB
522    FETCH(r0, 1)                        @ r0<- AAAA
523    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
524    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
525    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
526    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
527    GOTO_OPCODE(ip)                     @ jump to next instruction
528
529
530
531/* ------------------------------ */
532    .balign 64
533.L_OP_MOVE_RESULT: /* 0x0a */
534/* File: armv5te/OP_MOVE_RESULT.S */
535    /* for: move-result, move-result-object */
536    /* op vAA */
537    mov     r2, rINST, lsr #8           @ r2<- AA
538    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
539    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
541    SET_VREG(r0, r2)                    @ fp[AA]<- r0
542    GOTO_OPCODE(ip)                     @ jump to next instruction
543
544
545/* ------------------------------ */
546    .balign 64
547.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
548/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
549    /* move-result-wide vAA */
550    mov     r2, rINST, lsr #8           @ r2<- AA
551    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
552    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
553    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
554    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
555    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
556    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
557    GOTO_OPCODE(ip)                     @ jump to next instruction
558
559
560/* ------------------------------ */
561    .balign 64
562.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
563/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
564/* File: armv5te/OP_MOVE_RESULT.S */
565    /* for: move-result, move-result-object */
566    /* op vAA */
567    mov     r2, rINST, lsr #8           @ r2<- AA
568    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
569    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
571    SET_VREG(r0, r2)                    @ fp[AA]<- r0
572    GOTO_OPCODE(ip)                     @ jump to next instruction
573
574
575
576/* ------------------------------ */
577    .balign 64
578.L_OP_MOVE_EXCEPTION: /* 0x0d */
579/* File: armv5te/OP_MOVE_EXCEPTION.S */
580    /* move-exception vAA */
581    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
582    mov     r2, rINST, lsr #8           @ r2<- AA
583    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
584    mov     r1, #0                      @ r1<- 0
585    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
586    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
587    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
588    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
589    GOTO_OPCODE(ip)                     @ jump to next instruction
590
591
592/* ------------------------------ */
593    .balign 64
594.L_OP_RETURN_VOID: /* 0x0e */
595/* File: armv5te/OP_RETURN_VOID.S */
596    b       common_returnFromMethod
597
598
599/* ------------------------------ */
600    .balign 64
601.L_OP_RETURN: /* 0x0f */
602/* File: armv5te/OP_RETURN.S */
603    /*
604     * Return a 32-bit value.  Copies the return value into the "glue"
605     * structure, then jumps to the return handler.
606     *
607     * for: return, return-object
608     */
609    /* op vAA */
610    mov     r2, rINST, lsr #8           @ r2<- AA
611    GET_VREG(r0, r2)                    @ r0<- vAA
612    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
613    b       common_returnFromMethod
614
615
616/* ------------------------------ */
617    .balign 64
618.L_OP_RETURN_WIDE: /* 0x10 */
619/* File: armv5te/OP_RETURN_WIDE.S */
620    /*
621     * Return a 64-bit value.  Copies the return value into the "glue"
622     * structure, then jumps to the return handler.
623     */
624    /* return-wide vAA */
625    mov     r2, rINST, lsr #8           @ r2<- AA
626    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
627    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
628    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
629    stmia   r3, {r0-r1}                 @ retval<- r0/r1
630    b       common_returnFromMethod
631
632
633/* ------------------------------ */
634    .balign 64
635.L_OP_RETURN_OBJECT: /* 0x11 */
636/* File: armv5te/OP_RETURN_OBJECT.S */
637/* File: armv5te/OP_RETURN.S */
638    /*
639     * Return a 32-bit value.  Copies the return value into the "glue"
640     * structure, then jumps to the return handler.
641     *
642     * for: return, return-object
643     */
644    /* op vAA */
645    mov     r2, rINST, lsr #8           @ r2<- AA
646    GET_VREG(r0, r2)                    @ r0<- vAA
647    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
648    b       common_returnFromMethod
649
650
651
652/* ------------------------------ */
653    .balign 64
654.L_OP_CONST_4: /* 0x12 */
655/* File: armv5te/OP_CONST_4.S */
656    /* const/4 vA, #+B */
657    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
658    mov     r0, rINST, lsr #8           @ r0<- A+
659    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
660    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
661    and     r0, r0, #15
662    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
663    SET_VREG(r1, r0)                    @ fp[A]<- r1
664    GOTO_OPCODE(ip)                     @ execute next instruction
665
666
667/* ------------------------------ */
668    .balign 64
669.L_OP_CONST_16: /* 0x13 */
670/* File: armv5te/OP_CONST_16.S */
671    /* const/16 vAA, #+BBBB */
672    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
673    mov     r3, rINST, lsr #8           @ r3<- AA
674    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
675    SET_VREG(r0, r3)                    @ vAA<- r0
676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
677    GOTO_OPCODE(ip)                     @ jump to next instruction
678
679
680/* ------------------------------ */
681    .balign 64
682.L_OP_CONST: /* 0x14 */
683/* File: armv5te/OP_CONST.S */
684    /* const vAA, #+BBBBbbbb */
685    mov     r3, rINST, lsr #8           @ r3<- AA
686    FETCH(r0, 1)                        @ r0<- bbbb (low)
687    FETCH(r1, 2)                        @ r1<- BBBB (high)
688    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
689    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
690    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
691    SET_VREG(r0, r3)                    @ vAA<- r0
692    GOTO_OPCODE(ip)                     @ jump to next instruction
693
694
695/* ------------------------------ */
696    .balign 64
697.L_OP_CONST_HIGH16: /* 0x15 */
698/* File: armv5te/OP_CONST_HIGH16.S */
699    /* const/high16 vAA, #+BBBB0000 */
700    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
701    mov     r3, rINST, lsr #8           @ r3<- AA
702    mov     r0, r0, lsl #16             @ r0<- BBBB0000
703    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
704    SET_VREG(r0, r3)                    @ vAA<- r0
705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
706    GOTO_OPCODE(ip)                     @ jump to next instruction
707
708
709/* ------------------------------ */
710    .balign 64
711.L_OP_CONST_WIDE_16: /* 0x16 */
712/* File: armv5te/OP_CONST_WIDE_16.S */
713    /* const-wide/16 vAA, #+BBBB */
714    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
715    mov     r3, rINST, lsr #8           @ r3<- AA
716    mov     r1, r0, asr #31             @ r1<- ssssssss
717    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
718    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
719    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
720    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
721    GOTO_OPCODE(ip)                     @ jump to next instruction
722
723
724/* ------------------------------ */
725    .balign 64
726.L_OP_CONST_WIDE_32: /* 0x17 */
727/* File: armv5te/OP_CONST_WIDE_32.S */
728    /* const-wide/32 vAA, #+BBBBbbbb */
729    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
730    mov     r3, rINST, lsr #8           @ r3<- AA
731    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
732    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
733    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
734    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
735    mov     r1, r0, asr #31             @ r1<- ssssssss
736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
737    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
738    GOTO_OPCODE(ip)                     @ jump to next instruction
739
740
741/* ------------------------------ */
742    .balign 64
743.L_OP_CONST_WIDE: /* 0x18 */
744/* File: armv5te/OP_CONST_WIDE.S */
745    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
746    FETCH(r0, 1)                        @ r0<- bbbb (low)
747    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
748    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
749    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
750    FETCH(r3, 4)                        @ r3<- HHHH (high)
751    mov     r9, rINST, lsr #8           @ r9<- AA
752    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
753    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
754    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
755    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
756    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
757    GOTO_OPCODE(ip)                     @ jump to next instruction
758
759
760/* ------------------------------ */
761    .balign 64
762.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
763/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
764    /* const-wide/high16 vAA, #+BBBB000000000000 */
765    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
766    mov     r3, rINST, lsr #8           @ r3<- AA
767    mov     r0, #0                      @ r0<- 00000000
768    mov     r1, r1, lsl #16             @ r1<- BBBB0000
769    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
770    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
771    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
772    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
773    GOTO_OPCODE(ip)                     @ jump to next instruction
774
775
776/* ------------------------------ */
777    .balign 64
778.L_OP_CONST_STRING: /* 0x1a */
779/* File: armv5te/OP_CONST_STRING.S */
780    /* const/string vAA, String@BBBB */
781    FETCH(r1, 1)                        @ r1<- BBBB
782    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
783    mov     r9, rINST, lsr #8           @ r9<- AA
784    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
785    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
786    cmp     r0, #0                      @ not yet resolved?
787    beq     .LOP_CONST_STRING_resolve
788    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
790    SET_VREG(r0, r9)                    @ vAA<- r0
791    GOTO_OPCODE(ip)                     @ jump to next instruction
792
793/* ------------------------------ */
794    .balign 64
795.L_OP_CONST_STRING_JUMBO: /* 0x1b */
796/* File: armv5te/OP_CONST_STRING_JUMBO.S */
797    /* const/string vAA, String@BBBBBBBB */
798    FETCH(r0, 1)                        @ r0<- bbbb (low)
799    FETCH(r1, 2)                        @ r1<- BBBB (high)
800    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
801    mov     r9, rINST, lsr #8           @ r9<- AA
802    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
803    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
804    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
805    cmp     r0, #0
806    beq     .LOP_CONST_STRING_JUMBO_resolve
807    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
809    SET_VREG(r0, r9)                    @ vAA<- r0
810    GOTO_OPCODE(ip)                     @ jump to next instruction
811
812/* ------------------------------ */
813    .balign 64
814.L_OP_CONST_CLASS: /* 0x1c */
815/* File: armv5te/OP_CONST_CLASS.S */
816    /* const/class vAA, Class@BBBB */
817    FETCH(r1, 1)                        @ r1<- BBBB
818    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
819    mov     r9, rINST, lsr #8           @ r9<- AA
820    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
821    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
822    cmp     r0, #0                      @ not yet resolved?
823    beq     .LOP_CONST_CLASS_resolve
824    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
825    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
826    SET_VREG(r0, r9)                    @ vAA<- r0
827    GOTO_OPCODE(ip)                     @ jump to next instruction
828
829/* ------------------------------ */
830    .balign 64
831.L_OP_MONITOR_ENTER: /* 0x1d */
832/* File: armv5te/OP_MONITOR_ENTER.S */
833    /*
834     * Synchronize on an object.
835     */
836    /* monitor-enter vAA */
837    mov     r2, rINST, lsr #8           @ r2<- AA
838    GET_VREG(r1, r2)                    @ r1<- vAA (object)
839    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
840    cmp     r1, #0                      @ null object?
841    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
842    beq     common_errNullObject        @ null object, throw an exception
843    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
844    bl      dvmLockObject               @ call(self, obj)
845#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
846    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
847    ldr     r1, [r0, #offThread_exception] @ check for exception
848    cmp     r1, #0
849    bne     common_exceptionThrown      @ exception raised, bail out
850#endif
851    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
852    GOTO_OPCODE(ip)                     @ jump to next instruction
853
854
855/* ------------------------------ */
856    .balign 64
857.L_OP_MONITOR_EXIT: /* 0x1e */
858/* File: armv5te/OP_MONITOR_EXIT.S */
859    /*
860     * Unlock an object.
861     *
862     * Exceptions that occur when unlocking a monitor need to appear as
863     * if they happened at the following instruction.  See the Dalvik
864     * instruction spec.
865     */
866    /* monitor-exit vAA */
867    mov     r2, rINST, lsr #8           @ r2<- AA
868    EXPORT_PC()                         @ before fetch: export the PC
869    GET_VREG(r1, r2)                    @ r1<- vAA (object)
870    cmp     r1, #0                      @ null object?
871    beq     common_errNullObject        @ yes
872    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
873    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
874    cmp     r0, #0                      @ failed?
875    beq     common_exceptionThrown      @ yes, exception is pending
876    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
878    GOTO_OPCODE(ip)                     @ jump to next instruction
879
880
881/* ------------------------------ */
882    .balign 64
883.L_OP_CHECK_CAST: /* 0x1f */
884/* File: armv5te/OP_CHECK_CAST.S */
885    /*
886     * Check to see if a cast from one class to another is allowed.
887     */
888    /* check-cast vAA, class@BBBB */
889    mov     r3, rINST, lsr #8           @ r3<- AA
890    FETCH(r2, 1)                        @ r2<- BBBB
891    GET_VREG(r9, r3)                    @ r9<- object
892    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
893    cmp     r9, #0                      @ is object null?
894    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
895    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
896    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
897    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
898    cmp     r1, #0                      @ have we resolved this before?
899    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
900.LOP_CHECK_CAST_resolved:
901    cmp     r0, r1                      @ same class (trivial success)?
902    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
903.LOP_CHECK_CAST_okay:
904    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
905    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
906    GOTO_OPCODE(ip)                     @ jump to next instruction
907
908/* ------------------------------ */
909    .balign 64
910.L_OP_INSTANCE_OF: /* 0x20 */
911/* File: armv5te/OP_INSTANCE_OF.S */
912    /*
913     * Check to see if an object reference is an instance of a class.
914     *
915     * Most common situation is a non-null object, being compared against
916     * an already-resolved class.
917     */
918    /* instance-of vA, vB, class@CCCC */
919    mov     r3, rINST, lsr #12          @ r3<- B
920    mov     r9, rINST, lsr #8           @ r9<- A+
921    GET_VREG(r0, r3)                    @ r0<- vB (object)
922    and     r9, r9, #15                 @ r9<- A
923    cmp     r0, #0                      @ is object null?
924    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
925    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
926    FETCH(r3, 1)                        @ r3<- CCCC
927    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
928    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
929    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
930    cmp     r1, #0                      @ have we resolved this before?
931    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
932.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
933    cmp     r0, r1                      @ same class (trivial success)?
934    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
935    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
936
937/* ------------------------------ */
938    .balign 64
939.L_OP_ARRAY_LENGTH: /* 0x21 */
940/* File: armv5te/OP_ARRAY_LENGTH.S */
941    /*
942     * Return the length of an array.
943     */
944    mov     r1, rINST, lsr #12          @ r1<- B
945    mov     r2, rINST, lsr #8           @ r2<- A+
946    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
947    and     r2, r2, #15                 @ r2<- A
948    cmp     r0, #0                      @ is object null?
949    beq     common_errNullObject        @ yup, fail
950    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
951    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
952    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
953    SET_VREG(r3, r2)                    @ vB<- length
954    GOTO_OPCODE(ip)                     @ jump to next instruction
955
956
957/* ------------------------------ */
958    .balign 64
959.L_OP_NEW_INSTANCE: /* 0x22 */
960/* File: armv5te/OP_NEW_INSTANCE.S */
961    /*
962     * Create a new instance of a class.
963     */
964    /* new-instance vAA, class@BBBB */
965    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
966    FETCH(r1, 1)                        @ r1<- BBBB
967    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
968    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
969    EXPORT_PC()                         @ req'd for init, resolve, alloc
970    cmp     r0, #0                      @ already resolved?
971    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
972.LOP_NEW_INSTANCE_resolved:   @ r0=class
973    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
974    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
975    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
976.LOP_NEW_INSTANCE_initialized: @ r0=class
977    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
978    bl      dvmAllocObject              @ r0<- new object
979    b       .LOP_NEW_INSTANCE_finish          @ continue
980
981/* ------------------------------ */
982    .balign 64
983.L_OP_NEW_ARRAY: /* 0x23 */
984/* File: armv5te/OP_NEW_ARRAY.S */
985    /*
986     * Allocate an array of objects, specified with the array class
987     * and a count.
988     *
989     * The verifier guarantees that this is an array class, so we don't
990     * check for it here.
991     */
992    /* new-array vA, vB, class@CCCC */
993    mov     r0, rINST, lsr #12          @ r0<- B
994    FETCH(r2, 1)                        @ r2<- CCCC
995    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
996    GET_VREG(r1, r0)                    @ r1<- vB (array length)
997    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
998    cmp     r1, #0                      @ check length
999    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1000    bmi     common_errNegativeArraySize @ negative length, bail
1001    cmp     r0, #0                      @ already resolved?
1002    EXPORT_PC()                         @ req'd for resolve, alloc
1003    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1004    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1005
1006/* ------------------------------ */
1007    .balign 64
1008.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1009/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1010    /*
1011     * Create a new array with elements filled from registers.
1012     *
1013     * for: filled-new-array, filled-new-array/range
1014     */
1015    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1016    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1017    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1018    FETCH(r1, 1)                        @ r1<- BBBB
1019    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1020    EXPORT_PC()                         @ need for resolve and alloc
1021    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1022    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1023    cmp     r0, #0                      @ already resolved?
1024    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10258:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1026    mov     r2, #0                      @ r2<- false
1027    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1028    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1029    cmp     r0, #0                      @ got null?
1030    beq     common_exceptionThrown      @ yes, handle exception
1031    b       .LOP_FILLED_NEW_ARRAY_continue
1032
1033/* ------------------------------ */
1034    .balign 64
1035.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1036/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1037/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1038    /*
1039     * Create a new array with elements filled from registers.
1040     *
1041     * for: filled-new-array, filled-new-array/range
1042     */
1043    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1044    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1045    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1046    FETCH(r1, 1)                        @ r1<- BBBB
1047    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1048    EXPORT_PC()                         @ need for resolve and alloc
1049    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1050    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1051    cmp     r0, #0                      @ already resolved?
1052    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10538:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1054    mov     r2, #0                      @ r2<- false
1055    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1056    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1057    cmp     r0, #0                      @ got null?
1058    beq     common_exceptionThrown      @ yes, handle exception
1059    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1060
1061
1062/* ------------------------------ */
1063    .balign 64
1064.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1065/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1066    /* fill-array-data vAA, +BBBBBBBB */
1067    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1068    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1069    mov     r3, rINST, lsr #8           @ r3<- AA
1070    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1071    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1072    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1073    EXPORT_PC();
1074    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1075    cmp     r0, #0                      @ 0 means an exception is thrown
1076    beq     common_exceptionThrown      @ has exception
1077    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1079    GOTO_OPCODE(ip)                     @ jump to next instruction
1080
1081/* ------------------------------ */
1082    .balign 64
1083.L_OP_THROW: /* 0x27 */
1084/* File: armv5te/OP_THROW.S */
1085    /*
1086     * Throw an exception object in the current thread.
1087     */
1088    /* throw vAA */
1089    mov     r2, rINST, lsr #8           @ r2<- AA
1090    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1091    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1092    cmp     r1, #0                      @ null object?
1093    beq     common_errNullObject        @ yes, throw an NPE instead
1094    @ bypass dvmSetException, just store it
1095    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1096    b       common_exceptionThrown
1097
1098
1099/* ------------------------------ */
1100    .balign 64
1101.L_OP_GOTO: /* 0x28 */
1102/* File: armv5te/OP_GOTO.S */
1103    /*
1104     * Unconditional branch, 8-bit offset.
1105     *
1106     * The branch distance is a signed code-unit offset, which we need to
1107     * double to get a byte offset.
1108     */
1109    /* goto +AA */
1110    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1111    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1112    mov     r9, r9, lsl #1              @ r9<- byte offset
1113    bmi     common_backwardBranch       @ backward branch, do periodic checks
1114    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1116    GOTO_OPCODE(ip)                     @ jump to next instruction
1117
1118
1119/* ------------------------------ */
1120    .balign 64
1121.L_OP_GOTO_16: /* 0x29 */
1122/* File: armv5te/OP_GOTO_16.S */
1123    /*
1124     * Unconditional branch, 16-bit offset.
1125     *
1126     * The branch distance is a signed code-unit offset, which we need to
1127     * double to get a byte offset.
1128     */
1129    /* goto/16 +AAAA */
1130    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1131    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1132    bmi     common_backwardBranch       @ backward branch, do periodic checks
1133    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1134    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1135    GOTO_OPCODE(ip)                     @ jump to next instruction
1136
1137
1138/* ------------------------------ */
1139    .balign 64
1140.L_OP_GOTO_32: /* 0x2a */
1141/* File: armv5te/OP_GOTO_32.S */
1142    /*
1143     * Unconditional branch, 32-bit offset.
1144     *
1145     * The branch distance is a signed code-unit offset, which we need to
1146     * double to get a byte offset.
1147     *
1148     * Unlike most opcodes, this one is allowed to branch to itself, so
1149     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1150     * instruction doesn't affect the V flag, so we need to clear it
1151     * explicitly.
1152     */
1153    /* goto/32 +AAAAAAAA */
1154    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1155    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1156    cmp     ip, ip                      @ (clear V flag during stall)
1157    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1158    mov     r9, r0, asl #1              @ r9<- byte offset
1159    ble     common_backwardBranch       @ backward branch, do periodic checks
1160    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1162    GOTO_OPCODE(ip)                     @ jump to next instruction
1163
1164
1165/* ------------------------------ */
1166    .balign 64
1167.L_OP_PACKED_SWITCH: /* 0x2b */
1168/* File: armv5te/OP_PACKED_SWITCH.S */
1169    /*
1170     * Handle a packed-switch or sparse-switch instruction.  In both cases
1171     * we decode it and hand it off to a helper function.
1172     *
1173     * We don't really expect backward branches in a switch statement, but
1174     * they're perfectly legal, so we check for them here.
1175     *
1176     * for: packed-switch, sparse-switch
1177     */
1178    /* op vAA, +BBBB */
1179    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1180    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1181    mov     r3, rINST, lsr #8           @ r3<- AA
1182    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1183    GET_VREG(r1, r3)                    @ r1<- vAA
1184    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1185    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1186    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1187    bmi     common_backwardBranch       @ backward branch, do periodic checks
1188    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1189    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1191    GOTO_OPCODE(ip)                     @ jump to next instruction
1192
1193
1194/* ------------------------------ */
1195    .balign 64
1196.L_OP_SPARSE_SWITCH: /* 0x2c */
1197/* File: armv5te/OP_SPARSE_SWITCH.S */
1198/* File: armv5te/OP_PACKED_SWITCH.S */
1199    /*
1200     * Handle a packed-switch or sparse-switch instruction.  In both cases
1201     * we decode it and hand it off to a helper function.
1202     *
1203     * We don't really expect backward branches in a switch statement, but
1204     * they're perfectly legal, so we check for them here.
1205     *
1206     * for: packed-switch, sparse-switch
1207     */
1208    /* op vAA, +BBBB */
1209    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1210    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1211    mov     r3, rINST, lsr #8           @ r3<- AA
1212    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1213    GET_VREG(r1, r3)                    @ r1<- vAA
1214    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1215    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1216    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1217    bmi     common_backwardBranch       @ backward branch, do periodic checks
1218    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1219    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1221    GOTO_OPCODE(ip)                     @ jump to next instruction
1222
1223
1224
1225/* ------------------------------ */
1226    .balign 64
1227.L_OP_CMPL_FLOAT: /* 0x2d */
1228/* File: vfp/OP_CMPL_FLOAT.S */
1229    /*
1230     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1231     * destination register based on the results of the comparison.
1232     *
1233     * int compare(x, y) {
1234     *     if (x == y) {
1235     *         return 0;
1236     *     } else if (x > y) {
1237     *         return 1;
1238     *     } else if (x < y) {
1239     *         return -1;
1240     *     } else {
1241     *         return -1;
1242     *     }
1243     * }
1244     */
1245    /* op vAA, vBB, vCC */
1246    FETCH(r0, 1)                        @ r0<- CCBB
1247    and     r2, r0, #255                @ r2<- BB
1248    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1249    flds    s0, [r2]                    @ s0<- vBB
1250    mov     r3, r0, lsr #8              @ r3<- CC
1251    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1252    flds    s1, [r3]                    @ s1<- vCC
1253    mov     r9, rINST, lsr #8           @ r9<- AA
1254    fcmpes  s0, s1                      @ compare (vBB, vCC)
1255    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1256    mvn     r0, #0                      @ r0<- -1 (default)
1257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1258    fmstat                              @ export status flags
1259    movgt   r0, #1                      @ (greater than) r1<- 1
1260    moveq   r0, #0                      @ (equal) r1<- 0
1261    bl      .LOP_CMPL_FLOAT_finish          @ argh
1262
1263
1264/* ------------------------------ */
1265    .balign 64
1266.L_OP_CMPG_FLOAT: /* 0x2e */
1267/* File: vfp/OP_CMPG_FLOAT.S */
1268    /*
1269     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1270     * destination register based on the results of the comparison.
1271     *
1272     * int compare(x, y) {
1273     *     if (x == y) {
1274     *         return 0;
1275     *     } else if (x < y) {
1276     *         return -1;
1277     *     } else if (x > y) {
1278     *         return 1;
1279     *     } else {
1280     *         return 1;
1281     *     }
1282     * }
1283     */
1284    /* op vAA, vBB, vCC */
1285    FETCH(r0, 1)                        @ r0<- CCBB
1286    and     r2, r0, #255                @ r2<- BB
1287    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1288    flds    s0, [r2]                    @ s0<- vBB
1289    mov     r3, r0, lsr #8              @ r3<- CC
1290    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1291    flds    s1, [r3]                    @ s1<- vCC
1292    mov     r9, rINST, lsr #8           @ r9<- AA
1293    fcmpes  s0, s1                      @ compare (vBB, vCC)
1294    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1295    mov     r0, #1                      @ r0<- 1 (default)
1296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1297    fmstat                              @ export status flags
1298    mvnmi   r0, #0                      @ (less than) r1<- -1
1299    moveq   r0, #0                      @ (equal) r1<- 0
1300    bl      .LOP_CMPG_FLOAT_finish          @ argh
1301
1302
1303/* ------------------------------ */
1304    .balign 64
1305.L_OP_CMPL_DOUBLE: /* 0x2f */
1306/* File: vfp/OP_CMPL_DOUBLE.S */
1307    /*
1308     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1309     * destination register based on the results of the comparison.
1310     *
1311     * int compare(x, y) {
1312     *     if (x == y) {
1313     *         return 0;
1314     *     } else if (x > y) {
1315     *         return 1;
1316     *     } else if (x < y) {
1317     *         return -1;
1318     *     } else {
1319     *         return -1;
1320     *     }
1321     * }
1322     */
1323    /* op vAA, vBB, vCC */
1324    FETCH(r0, 1)                        @ r0<- CCBB
1325    and     r2, r0, #255                @ r2<- BB
1326    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1327    fldd    d0, [r2]                    @ d0<- vBB
1328    mov     r3, r0, lsr #8              @ r3<- CC
1329    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1330    fldd    d1, [r3]                    @ d1<- vCC
1331    mov     r9, rINST, lsr #8           @ r9<- AA
1332    fcmped  d0, d1                      @ compare (vBB, vCC)
1333    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1334    mvn     r0, #0                      @ r0<- -1 (default)
1335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1336    fmstat                              @ export status flags
1337    movgt   r0, #1                      @ (greater than) r1<- 1
1338    moveq   r0, #0                      @ (equal) r1<- 0
1339    bl      .LOP_CMPL_DOUBLE_finish          @ argh
1340
1341
1342/* ------------------------------ */
1343    .balign 64
1344.L_OP_CMPG_DOUBLE: /* 0x30 */
1345/* File: vfp/OP_CMPG_DOUBLE.S */
1346    /*
1347     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1348     * destination register based on the results of the comparison.
1349     *
1350     * int compare(x, y) {
1351     *     if (x == y) {
1352     *         return 0;
1353     *     } else if (x < y) {
1354     *         return -1;
1355     *     } else if (x > y) {
1356     *         return 1;
1357     *     } else {
1358     *         return 1;
1359     *     }
1360     * }
1361     */
1362    /* op vAA, vBB, vCC */
1363    FETCH(r0, 1)                        @ r0<- CCBB
1364    and     r2, r0, #255                @ r2<- BB
1365    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1366    fldd    d0, [r2]                    @ d0<- vBB
1367    mov     r3, r0, lsr #8              @ r3<- CC
1368    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1369    fldd    d1, [r3]                    @ d1<- vCC
1370    mov     r9, rINST, lsr #8           @ r9<- AA
1371    fcmped  d0, d1                      @ compare (vBB, vCC)
1372    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1373    mov     r0, #1                      @ r0<- 1 (default)
1374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1375    fmstat                              @ export status flags
1376    mvnmi   r0, #0                      @ (less than) r1<- -1
1377    moveq   r0, #0                      @ (equal) r1<- 0
1378    bl      .LOP_CMPG_DOUBLE_finish          @ argh
1379
1380
1381/* ------------------------------ */
1382    .balign 64
1383.L_OP_CMP_LONG: /* 0x31 */
1384/* File: armv5te/OP_CMP_LONG.S */
1385    /*
1386     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1387     * register based on the results of the comparison.
1388     *
1389     * We load the full values with LDM, but in practice many values could
1390     * be resolved by only looking at the high word.  This could be made
1391     * faster or slower by splitting the LDM into a pair of LDRs.
1392     *
1393     * If we just wanted to set condition flags, we could do this:
1394     *  subs    ip, r0, r2
1395     *  sbcs    ip, r1, r3
1396     *  subeqs  ip, r0, r2
1397     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1398     * integer value, which we can do with 2 conditional mov/mvn instructions
1399     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1400     * us a constant 5-cycle path plus a branch at the end to the
1401     * instruction epilogue code.  The multi-compare approach below needs
1402     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1403     * in the worst case (the 64-bit values are equal).
1404     */
1405    /* cmp-long vAA, vBB, vCC */
1406    FETCH(r0, 1)                        @ r0<- CCBB
1407    mov     r9, rINST, lsr #8           @ r9<- AA
1408    and     r2, r0, #255                @ r2<- BB
1409    mov     r3, r0, lsr #8              @ r3<- CC
1410    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1411    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1412    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1413    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1414    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1415    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1416    bgt     .LOP_CMP_LONG_greater
1417    subs    r1, r0, r2                  @ r1<- r0 - r2
1418    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1419    bne     .LOP_CMP_LONG_less
1420    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1421
1422/* ------------------------------ */
1423    .balign 64
1424.L_OP_IF_EQ: /* 0x32 */
1425/* File: armv5te/OP_IF_EQ.S */
1426/* File: armv5te/bincmp.S */
1427    /*
1428     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1429     * fragment that specifies the *reverse* comparison to perform, e.g.
1430     * for "if-le" you would use "gt".
1431     *
1432     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1433     */
1434    /* if-cmp vA, vB, +CCCC */
1435    mov     r0, rINST, lsr #8           @ r0<- A+
1436    mov     r1, rINST, lsr #12          @ r1<- B
1437    and     r0, r0, #15
1438    GET_VREG(r3, r1)                    @ r3<- vB
1439    GET_VREG(r2, r0)                    @ r2<- vA
1440    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1441    cmp     r2, r3                      @ compare (vA, vB)
1442    bne  1f                      @ branch to 1 if comparison failed
1443    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1444    movs    r9, r9, asl #1              @ convert to bytes, check sign
1445    bmi     common_backwardBranch       @ yes, do periodic checks
14461:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1448    GOTO_OPCODE(ip)                     @ jump to next instruction
1449
1450
1451
1452/* ------------------------------ */
1453    .balign 64
1454.L_OP_IF_NE: /* 0x33 */
1455/* File: armv5te/OP_IF_NE.S */
1456/* File: armv5te/bincmp.S */
1457    /*
1458     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1459     * fragment that specifies the *reverse* comparison to perform, e.g.
1460     * for "if-le" you would use "gt".
1461     *
1462     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1463     */
1464    /* if-cmp vA, vB, +CCCC */
1465    mov     r0, rINST, lsr #8           @ r0<- A+
1466    mov     r1, rINST, lsr #12          @ r1<- B
1467    and     r0, r0, #15
1468    GET_VREG(r3, r1)                    @ r3<- vB
1469    GET_VREG(r2, r0)                    @ r2<- vA
1470    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1471    cmp     r2, r3                      @ compare (vA, vB)
1472    beq  1f                      @ branch to 1 if comparison failed
1473    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1474    movs    r9, r9, asl #1              @ convert to bytes, check sign
1475    bmi     common_backwardBranch       @ yes, do periodic checks
14761:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1477    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1478    GOTO_OPCODE(ip)                     @ jump to next instruction
1479
1480
1481
1482/* ------------------------------ */
1483    .balign 64
1484.L_OP_IF_LT: /* 0x34 */
1485/* File: armv5te/OP_IF_LT.S */
1486/* File: armv5te/bincmp.S */
1487    /*
1488     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1489     * fragment that specifies the *reverse* comparison to perform, e.g.
1490     * for "if-le" you would use "gt".
1491     *
1492     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1493     */
1494    /* if-cmp vA, vB, +CCCC */
1495    mov     r0, rINST, lsr #8           @ r0<- A+
1496    mov     r1, rINST, lsr #12          @ r1<- B
1497    and     r0, r0, #15
1498    GET_VREG(r3, r1)                    @ r3<- vB
1499    GET_VREG(r2, r0)                    @ r2<- vA
1500    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1501    cmp     r2, r3                      @ compare (vA, vB)
1502    bge  1f                      @ branch to 1 if comparison failed
1503    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1504    movs    r9, r9, asl #1              @ convert to bytes, check sign
1505    bmi     common_backwardBranch       @ yes, do periodic checks
15061:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1507    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1508    GOTO_OPCODE(ip)                     @ jump to next instruction
1509
1510
1511
1512/* ------------------------------ */
1513    .balign 64
1514.L_OP_IF_GE: /* 0x35 */
1515/* File: armv5te/OP_IF_GE.S */
1516/* File: armv5te/bincmp.S */
1517    /*
1518     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1519     * fragment that specifies the *reverse* comparison to perform, e.g.
1520     * for "if-le" you would use "gt".
1521     *
1522     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1523     */
1524    /* if-cmp vA, vB, +CCCC */
1525    mov     r0, rINST, lsr #8           @ r0<- A+
1526    mov     r1, rINST, lsr #12          @ r1<- B
1527    and     r0, r0, #15
1528    GET_VREG(r3, r1)                    @ r3<- vB
1529    GET_VREG(r2, r0)                    @ r2<- vA
1530    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1531    cmp     r2, r3                      @ compare (vA, vB)
1532    blt  1f                      @ branch to 1 if comparison failed
1533    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1534    movs    r9, r9, asl #1              @ convert to bytes, check sign
1535    bmi     common_backwardBranch       @ yes, do periodic checks
15361:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1538    GOTO_OPCODE(ip)                     @ jump to next instruction
1539
1540
1541
1542/* ------------------------------ */
1543    .balign 64
1544.L_OP_IF_GT: /* 0x36 */
1545/* File: armv5te/OP_IF_GT.S */
1546/* File: armv5te/bincmp.S */
1547    /*
1548     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1549     * fragment that specifies the *reverse* comparison to perform, e.g.
1550     * for "if-le" you would use "gt".
1551     *
1552     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1553     */
1554    /* if-cmp vA, vB, +CCCC */
1555    mov     r0, rINST, lsr #8           @ r0<- A+
1556    mov     r1, rINST, lsr #12          @ r1<- B
1557    and     r0, r0, #15
1558    GET_VREG(r3, r1)                    @ r3<- vB
1559    GET_VREG(r2, r0)                    @ r2<- vA
1560    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1561    cmp     r2, r3                      @ compare (vA, vB)
1562    ble  1f                      @ branch to 1 if comparison failed
1563    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1564    movs    r9, r9, asl #1              @ convert to bytes, check sign
1565    bmi     common_backwardBranch       @ yes, do periodic checks
15661:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1568    GOTO_OPCODE(ip)                     @ jump to next instruction
1569
1570
1571
1572/* ------------------------------ */
1573    .balign 64
1574.L_OP_IF_LE: /* 0x37 */
1575/* File: armv5te/OP_IF_LE.S */
1576/* File: armv5te/bincmp.S */
1577    /*
1578     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1579     * fragment that specifies the *reverse* comparison to perform, e.g.
1580     * for "if-le" you would use "gt".
1581     *
1582     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1583     */
1584    /* if-cmp vA, vB, +CCCC */
1585    mov     r0, rINST, lsr #8           @ r0<- A+
1586    mov     r1, rINST, lsr #12          @ r1<- B
1587    and     r0, r0, #15
1588    GET_VREG(r3, r1)                    @ r3<- vB
1589    GET_VREG(r2, r0)                    @ r2<- vA
1590    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1591    cmp     r2, r3                      @ compare (vA, vB)
1592    bgt  1f                      @ branch to 1 if comparison failed
1593    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1594    movs    r9, r9, asl #1              @ convert to bytes, check sign
1595    bmi     common_backwardBranch       @ yes, do periodic checks
15961:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1597    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1598    GOTO_OPCODE(ip)                     @ jump to next instruction
1599
1600
1601
1602/* ------------------------------ */
1603    .balign 64
1604.L_OP_IF_EQZ: /* 0x38 */
1605/* File: armv5te/OP_IF_EQZ.S */
1606/* File: armv5te/zcmp.S */
1607    /*
1608     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1609     * fragment that specifies the *reverse* comparison to perform, e.g.
1610     * for "if-le" you would use "gt".
1611     *
1612     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1613     */
1614    /* if-cmp vAA, +BBBB */
1615    mov     r0, rINST, lsr #8           @ r0<- AA
1616    GET_VREG(r2, r0)                    @ r2<- vAA
1617    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1618    cmp     r2, #0                      @ compare (vA, 0)
1619    bne  1f                      @ branch to 1 if comparison failed
1620    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1621    movs    r9, r9, asl #1              @ convert to bytes, check sign
1622    bmi     common_backwardBranch       @ backward branch, do periodic checks
16231:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1625    GOTO_OPCODE(ip)                     @ jump to next instruction
1626
1627
1628
1629/* ------------------------------ */
1630    .balign 64
1631.L_OP_IF_NEZ: /* 0x39 */
1632/* File: armv5te/OP_IF_NEZ.S */
1633/* File: armv5te/zcmp.S */
1634    /*
1635     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1636     * fragment that specifies the *reverse* comparison to perform, e.g.
1637     * for "if-le" you would use "gt".
1638     *
1639     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1640     */
1641    /* if-cmp vAA, +BBBB */
1642    mov     r0, rINST, lsr #8           @ r0<- AA
1643    GET_VREG(r2, r0)                    @ r2<- vAA
1644    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1645    cmp     r2, #0                      @ compare (vA, 0)
1646    beq  1f                      @ branch to 1 if comparison failed
1647    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1648    movs    r9, r9, asl #1              @ convert to bytes, check sign
1649    bmi     common_backwardBranch       @ backward branch, do periodic checks
16501:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1651    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1652    GOTO_OPCODE(ip)                     @ jump to next instruction
1653
1654
1655
1656/* ------------------------------ */
1657    .balign 64
1658.L_OP_IF_LTZ: /* 0x3a */
1659/* File: armv5te/OP_IF_LTZ.S */
1660/* File: armv5te/zcmp.S */
1661    /*
1662     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1663     * fragment that specifies the *reverse* comparison to perform, e.g.
1664     * for "if-le" you would use "gt".
1665     *
1666     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1667     */
1668    /* if-cmp vAA, +BBBB */
1669    mov     r0, rINST, lsr #8           @ r0<- AA
1670    GET_VREG(r2, r0)                    @ r2<- vAA
1671    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1672    cmp     r2, #0                      @ compare (vA, 0)
1673    bge  1f                      @ branch to 1 if comparison failed
1674    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1675    movs    r9, r9, asl #1              @ convert to bytes, check sign
1676    bmi     common_backwardBranch       @ backward branch, do periodic checks
16771:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1678    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1679    GOTO_OPCODE(ip)                     @ jump to next instruction
1680
1681
1682
1683/* ------------------------------ */
1684    .balign 64
1685.L_OP_IF_GEZ: /* 0x3b */
1686/* File: armv5te/OP_IF_GEZ.S */
1687/* File: armv5te/zcmp.S */
1688    /*
1689     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1690     * fragment that specifies the *reverse* comparison to perform, e.g.
1691     * for "if-le" you would use "gt".
1692     *
1693     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1694     */
1695    /* if-cmp vAA, +BBBB */
1696    mov     r0, rINST, lsr #8           @ r0<- AA
1697    GET_VREG(r2, r0)                    @ r2<- vAA
1698    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1699    cmp     r2, #0                      @ compare (vA, 0)
1700    blt  1f                      @ branch to 1 if comparison failed
1701    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1702    movs    r9, r9, asl #1              @ convert to bytes, check sign
1703    bmi     common_backwardBranch       @ backward branch, do periodic checks
17041:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1706    GOTO_OPCODE(ip)                     @ jump to next instruction
1707
1708
1709
1710/* ------------------------------ */
1711    .balign 64
1712.L_OP_IF_GTZ: /* 0x3c */
1713/* File: armv5te/OP_IF_GTZ.S */
1714/* File: armv5te/zcmp.S */
1715    /*
1716     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1717     * fragment that specifies the *reverse* comparison to perform, e.g.
1718     * for "if-le" you would use "gt".
1719     *
1720     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1721     */
1722    /* if-cmp vAA, +BBBB */
1723    mov     r0, rINST, lsr #8           @ r0<- AA
1724    GET_VREG(r2, r0)                    @ r2<- vAA
1725    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1726    cmp     r2, #0                      @ compare (vA, 0)
1727    ble  1f                      @ branch to 1 if comparison failed
1728    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1729    movs    r9, r9, asl #1              @ convert to bytes, check sign
1730    bmi     common_backwardBranch       @ backward branch, do periodic checks
17311:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1733    GOTO_OPCODE(ip)                     @ jump to next instruction
1734
1735
1736
1737/* ------------------------------ */
1738    .balign 64
1739.L_OP_IF_LEZ: /* 0x3d */
1740/* File: armv5te/OP_IF_LEZ.S */
1741/* File: armv5te/zcmp.S */
1742    /*
1743     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1744     * fragment that specifies the *reverse* comparison to perform, e.g.
1745     * for "if-le" you would use "gt".
1746     *
1747     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1748     */
1749    /* if-cmp vAA, +BBBB */
1750    mov     r0, rINST, lsr #8           @ r0<- AA
1751    GET_VREG(r2, r0)                    @ r2<- vAA
1752    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1753    cmp     r2, #0                      @ compare (vA, 0)
1754    bgt  1f                      @ branch to 1 if comparison failed
1755    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1756    movs    r9, r9, asl #1              @ convert to bytes, check sign
1757    bmi     common_backwardBranch       @ backward branch, do periodic checks
17581:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1760    GOTO_OPCODE(ip)                     @ jump to next instruction
1761
1762
1763
1764/* ------------------------------ */
1765    .balign 64
1766.L_OP_UNUSED_3E: /* 0x3e */
1767/* File: armv5te/OP_UNUSED_3E.S */
1768/* File: armv5te/unused.S */
1769    bl      common_abort
1770
1771
1772
1773/* ------------------------------ */
1774    .balign 64
1775.L_OP_UNUSED_3F: /* 0x3f */
1776/* File: armv5te/OP_UNUSED_3F.S */
1777/* File: armv5te/unused.S */
1778    bl      common_abort
1779
1780
1781
1782/* ------------------------------ */
1783    .balign 64
1784.L_OP_UNUSED_40: /* 0x40 */
1785/* File: armv5te/OP_UNUSED_40.S */
1786/* File: armv5te/unused.S */
1787    bl      common_abort
1788
1789
1790
1791/* ------------------------------ */
1792    .balign 64
1793.L_OP_UNUSED_41: /* 0x41 */
1794/* File: armv5te/OP_UNUSED_41.S */
1795/* File: armv5te/unused.S */
1796    bl      common_abort
1797
1798
1799
1800/* ------------------------------ */
1801    .balign 64
1802.L_OP_UNUSED_42: /* 0x42 */
1803/* File: armv5te/OP_UNUSED_42.S */
1804/* File: armv5te/unused.S */
1805    bl      common_abort
1806
1807
1808
1809/* ------------------------------ */
1810    .balign 64
1811.L_OP_UNUSED_43: /* 0x43 */
1812/* File: armv5te/OP_UNUSED_43.S */
1813/* File: armv5te/unused.S */
1814    bl      common_abort
1815
1816
1817
1818/* ------------------------------ */
1819    .balign 64
1820.L_OP_AGET: /* 0x44 */
1821/* File: armv5te/OP_AGET.S */
1822    /*
1823     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1824     *
1825     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1826     * instructions.  We use a pair of FETCH_Bs instead.
1827     *
1828     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1829     */
1830    /* op vAA, vBB, vCC */
1831    FETCH_B(r2, 1, 0)                   @ r2<- BB
1832    mov     r9, rINST, lsr #8           @ r9<- AA
1833    FETCH_B(r3, 1, 1)                   @ r3<- CC
1834    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1835    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1836    cmp     r0, #0                      @ null array object?
1837    beq     common_errNullObject        @ yes, bail
1838    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1839    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1840    cmp     r1, r3                      @ compare unsigned index, length
1841    bcs     common_errArrayIndex        @ index >= length, bail
1842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1843    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1845    SET_VREG(r2, r9)                    @ vAA<- r2
1846    GOTO_OPCODE(ip)                     @ jump to next instruction
1847
1848
1849/* ------------------------------ */
1850    .balign 64
1851.L_OP_AGET_WIDE: /* 0x45 */
1852/* File: armv5te/OP_AGET_WIDE.S */
1853    /*
1854     * Array get, 64 bits.  vAA <- vBB[vCC].
1855     *
1856     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1857     */
1858    /* aget-wide vAA, vBB, vCC */
1859    FETCH(r0, 1)                        @ r0<- CCBB
1860    mov     r9, rINST, lsr #8           @ r9<- AA
1861    and     r2, r0, #255                @ r2<- BB
1862    mov     r3, r0, lsr #8              @ r3<- CC
1863    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1864    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1865    cmp     r0, #0                      @ null array object?
1866    beq     common_errNullObject        @ yes, bail
1867    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1868    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
1869    cmp     r1, r3                      @ compare unsigned index, length
1870    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
1871    b       common_errArrayIndex        @ index >= length, bail
1872    @ May want to swap the order of these two branches depending on how the
1873    @ branch prediction (if any) handles conditional forward branches vs.
1874    @ unconditional forward branches.
1875
1876/* ------------------------------ */
1877    .balign 64
1878.L_OP_AGET_OBJECT: /* 0x46 */
1879/* File: armv5te/OP_AGET_OBJECT.S */
1880/* File: armv5te/OP_AGET.S */
1881    /*
1882     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1883     *
1884     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1885     * instructions.  We use a pair of FETCH_Bs instead.
1886     *
1887     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1888     */
1889    /* op vAA, vBB, vCC */
1890    FETCH_B(r2, 1, 0)                   @ r2<- BB
1891    mov     r9, rINST, lsr #8           @ r9<- AA
1892    FETCH_B(r3, 1, 1)                   @ r3<- CC
1893    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1894    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1895    cmp     r0, #0                      @ null array object?
1896    beq     common_errNullObject        @ yes, bail
1897    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1898    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1899    cmp     r1, r3                      @ compare unsigned index, length
1900    bcs     common_errArrayIndex        @ index >= length, bail
1901    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1902    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1904    SET_VREG(r2, r9)                    @ vAA<- r2
1905    GOTO_OPCODE(ip)                     @ jump to next instruction
1906
1907
1908
1909/* ------------------------------ */
1910    .balign 64
1911.L_OP_AGET_BOOLEAN: /* 0x47 */
1912/* File: armv5te/OP_AGET_BOOLEAN.S */
1913/* File: armv5te/OP_AGET.S */
1914    /*
1915     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1916     *
1917     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1918     * instructions.  We use a pair of FETCH_Bs instead.
1919     *
1920     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1921     */
1922    /* op vAA, vBB, vCC */
1923    FETCH_B(r2, 1, 0)                   @ r2<- BB
1924    mov     r9, rINST, lsr #8           @ r9<- AA
1925    FETCH_B(r3, 1, 1)                   @ r3<- CC
1926    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1927    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1928    cmp     r0, #0                      @ null array object?
1929    beq     common_errNullObject        @ yes, bail
1930    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1931    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1932    cmp     r1, r3                      @ compare unsigned index, length
1933    bcs     common_errArrayIndex        @ index >= length, bail
1934    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1935    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1936    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1937    SET_VREG(r2, r9)                    @ vAA<- r2
1938    GOTO_OPCODE(ip)                     @ jump to next instruction
1939
1940
1941
1942/* ------------------------------ */
1943    .balign 64
1944.L_OP_AGET_BYTE: /* 0x48 */
1945/* File: armv5te/OP_AGET_BYTE.S */
1946/* File: armv5te/OP_AGET.S */
1947    /*
1948     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1949     *
1950     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1951     * instructions.  We use a pair of FETCH_Bs instead.
1952     *
1953     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1954     */
1955    /* op vAA, vBB, vCC */
1956    FETCH_B(r2, 1, 0)                   @ r2<- BB
1957    mov     r9, rINST, lsr #8           @ r9<- AA
1958    FETCH_B(r3, 1, 1)                   @ r3<- CC
1959    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1960    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1961    cmp     r0, #0                      @ null array object?
1962    beq     common_errNullObject        @ yes, bail
1963    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1964    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
1965    cmp     r1, r3                      @ compare unsigned index, length
1966    bcs     common_errArrayIndex        @ index >= length, bail
1967    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1968    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1969    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1970    SET_VREG(r2, r9)                    @ vAA<- r2
1971    GOTO_OPCODE(ip)                     @ jump to next instruction
1972
1973
1974
1975/* ------------------------------ */
1976    .balign 64
1977.L_OP_AGET_CHAR: /* 0x49 */
1978/* File: armv5te/OP_AGET_CHAR.S */
1979/* File: armv5te/OP_AGET.S */
1980    /*
1981     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1982     *
1983     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1984     * instructions.  We use a pair of FETCH_Bs instead.
1985     *
1986     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1987     */
1988    /* op vAA, vBB, vCC */
1989    FETCH_B(r2, 1, 0)                   @ r2<- BB
1990    mov     r9, rINST, lsr #8           @ r9<- AA
1991    FETCH_B(r3, 1, 1)                   @ r3<- CC
1992    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1993    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1994    cmp     r0, #0                      @ null array object?
1995    beq     common_errNullObject        @ yes, bail
1996    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1997    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
1998    cmp     r1, r3                      @ compare unsigned index, length
1999    bcs     common_errArrayIndex        @ index >= length, bail
2000    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2001    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2003    SET_VREG(r2, r9)                    @ vAA<- r2
2004    GOTO_OPCODE(ip)                     @ jump to next instruction
2005
2006
2007
2008/* ------------------------------ */
2009    .balign 64
2010.L_OP_AGET_SHORT: /* 0x4a */
2011/* File: armv5te/OP_AGET_SHORT.S */
2012/* File: armv5te/OP_AGET.S */
2013    /*
2014     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2015     *
2016     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2017     * instructions.  We use a pair of FETCH_Bs instead.
2018     *
2019     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2020     */
2021    /* op vAA, vBB, vCC */
2022    FETCH_B(r2, 1, 0)                   @ r2<- BB
2023    mov     r9, rINST, lsr #8           @ r9<- AA
2024    FETCH_B(r3, 1, 1)                   @ r3<- CC
2025    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2026    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2027    cmp     r0, #0                      @ null array object?
2028    beq     common_errNullObject        @ yes, bail
2029    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2030    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2031    cmp     r1, r3                      @ compare unsigned index, length
2032    bcs     common_errArrayIndex        @ index >= length, bail
2033    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2034    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2035    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2036    SET_VREG(r2, r9)                    @ vAA<- r2
2037    GOTO_OPCODE(ip)                     @ jump to next instruction
2038
2039
2040
2041/* ------------------------------ */
2042    .balign 64
2043.L_OP_APUT: /* 0x4b */
2044/* File: armv5te/OP_APUT.S */
2045    /*
2046     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2047     *
2048     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2049     * instructions.  We use a pair of FETCH_Bs instead.
2050     *
2051     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2052     */
2053    /* op vAA, vBB, vCC */
2054    FETCH_B(r2, 1, 0)                   @ r2<- BB
2055    mov     r9, rINST, lsr #8           @ r9<- AA
2056    FETCH_B(r3, 1, 1)                   @ r3<- CC
2057    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2058    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2059    cmp     r0, #0                      @ null array object?
2060    beq     common_errNullObject        @ yes, bail
2061    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2062    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2063    cmp     r1, r3                      @ compare unsigned index, length
2064    bcs     common_errArrayIndex        @ index >= length, bail
2065    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2066    GET_VREG(r2, r9)                    @ r2<- vAA
2067    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2068    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2069    GOTO_OPCODE(ip)                     @ jump to next instruction
2070
2071
2072/* ------------------------------ */
2073    .balign 64
2074.L_OP_APUT_WIDE: /* 0x4c */
2075/* File: armv5te/OP_APUT_WIDE.S */
2076    /*
2077     * Array put, 64 bits.  vBB[vCC] <- vAA.
2078     *
2079     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2080     */
2081    /* aput-wide vAA, vBB, vCC */
2082    FETCH(r0, 1)                        @ r0<- CCBB
2083    mov     r9, rINST, lsr #8           @ r9<- AA
2084    and     r2, r0, #255                @ r2<- BB
2085    mov     r3, r0, lsr #8              @ r3<- CC
2086    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2087    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2088    cmp     r0, #0                      @ null array object?
2089    beq     common_errNullObject        @ yes, bail
2090    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2091    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2092    cmp     r1, r3                      @ compare unsigned index, length
2093    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2094    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2095    b       common_errArrayIndex        @ index >= length, bail
2096    @ May want to swap the order of these two branches depending on how the
2097    @ branch prediction (if any) handles conditional forward branches vs.
2098    @ unconditional forward branches.
2099
2100/* ------------------------------ */
2101    .balign 64
2102.L_OP_APUT_OBJECT: /* 0x4d */
2103/* File: armv5te/OP_APUT_OBJECT.S */
2104    /*
2105     * Store an object into an array.  vBB[vCC] <- vAA.
2106     *
2107     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2108     * instructions.  We use a pair of FETCH_Bs instead.
2109     */
2110    /* op vAA, vBB, vCC */
2111    FETCH(r0, 1)                        @ r0<- CCBB
2112    mov     r9, rINST, lsr #8           @ r9<- AA
2113    and     r2, r0, #255                @ r2<- BB
2114    mov     r3, r0, lsr #8              @ r3<- CC
2115    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2116    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2117    cmp     r1, #0                      @ null array object?
2118    GET_VREG(r9, r9)                    @ r9<- vAA
2119    beq     common_errNullObject        @ yes, bail
2120    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2121    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2122    cmp     r0, r3                      @ compare unsigned index, length
2123    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2124    b       common_errArrayIndex        @ index >= length, bail
2125
2126
2127/* ------------------------------ */
2128    .balign 64
2129.L_OP_APUT_BOOLEAN: /* 0x4e */
2130/* File: armv5te/OP_APUT_BOOLEAN.S */
2131/* File: armv5te/OP_APUT.S */
2132    /*
2133     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2134     *
2135     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2136     * instructions.  We use a pair of FETCH_Bs instead.
2137     *
2138     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2139     */
2140    /* op vAA, vBB, vCC */
2141    FETCH_B(r2, 1, 0)                   @ r2<- BB
2142    mov     r9, rINST, lsr #8           @ r9<- AA
2143    FETCH_B(r3, 1, 1)                   @ r3<- CC
2144    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2145    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2146    cmp     r0, #0                      @ null array object?
2147    beq     common_errNullObject        @ yes, bail
2148    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2149    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2150    cmp     r1, r3                      @ compare unsigned index, length
2151    bcs     common_errArrayIndex        @ index >= length, bail
2152    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2153    GET_VREG(r2, r9)                    @ r2<- vAA
2154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2155    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2156    GOTO_OPCODE(ip)                     @ jump to next instruction
2157
2158
2159
2160/* ------------------------------ */
2161    .balign 64
2162.L_OP_APUT_BYTE: /* 0x4f */
2163/* File: armv5te/OP_APUT_BYTE.S */
2164/* File: armv5te/OP_APUT.S */
2165    /*
2166     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2167     *
2168     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2169     * instructions.  We use a pair of FETCH_Bs instead.
2170     *
2171     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2172     */
2173    /* op vAA, vBB, vCC */
2174    FETCH_B(r2, 1, 0)                   @ r2<- BB
2175    mov     r9, rINST, lsr #8           @ r9<- AA
2176    FETCH_B(r3, 1, 1)                   @ r3<- CC
2177    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2178    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2179    cmp     r0, #0                      @ null array object?
2180    beq     common_errNullObject        @ yes, bail
2181    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2182    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2183    cmp     r1, r3                      @ compare unsigned index, length
2184    bcs     common_errArrayIndex        @ index >= length, bail
2185    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2186    GET_VREG(r2, r9)                    @ r2<- vAA
2187    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2188    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2189    GOTO_OPCODE(ip)                     @ jump to next instruction
2190
2191
2192
2193/* ------------------------------ */
2194    .balign 64
2195.L_OP_APUT_CHAR: /* 0x50 */
2196/* File: armv5te/OP_APUT_CHAR.S */
2197/* File: armv5te/OP_APUT.S */
2198    /*
2199     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2200     *
2201     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2202     * instructions.  We use a pair of FETCH_Bs instead.
2203     *
2204     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2205     */
2206    /* op vAA, vBB, vCC */
2207    FETCH_B(r2, 1, 0)                   @ r2<- BB
2208    mov     r9, rINST, lsr #8           @ r9<- AA
2209    FETCH_B(r3, 1, 1)                   @ r3<- CC
2210    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2211    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2212    cmp     r0, #0                      @ null array object?
2213    beq     common_errNullObject        @ yes, bail
2214    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2215    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2216    cmp     r1, r3                      @ compare unsigned index, length
2217    bcs     common_errArrayIndex        @ index >= length, bail
2218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2219    GET_VREG(r2, r9)                    @ r2<- vAA
2220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2221    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2222    GOTO_OPCODE(ip)                     @ jump to next instruction
2223
2224
2225
2226/* ------------------------------ */
2227    .balign 64
2228.L_OP_APUT_SHORT: /* 0x51 */
2229/* File: armv5te/OP_APUT_SHORT.S */
2230/* File: armv5te/OP_APUT.S */
2231    /*
2232     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2233     *
2234     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2235     * instructions.  We use a pair of FETCH_Bs instead.
2236     *
2237     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2238     */
2239    /* op vAA, vBB, vCC */
2240    FETCH_B(r2, 1, 0)                   @ r2<- BB
2241    mov     r9, rINST, lsr #8           @ r9<- AA
2242    FETCH_B(r3, 1, 1)                   @ r3<- CC
2243    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2244    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2245    cmp     r0, #0                      @ null array object?
2246    beq     common_errNullObject        @ yes, bail
2247    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2248    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2249    cmp     r1, r3                      @ compare unsigned index, length
2250    bcs     common_errArrayIndex        @ index >= length, bail
2251    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2252    GET_VREG(r2, r9)                    @ r2<- vAA
2253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2254    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2255    GOTO_OPCODE(ip)                     @ jump to next instruction
2256
2257
2258
2259/* ------------------------------ */
2260    .balign 64
2261.L_OP_IGET: /* 0x52 */
2262/* File: armv5te/OP_IGET.S */
2263    /*
2264     * General 32-bit instance field get.
2265     *
2266     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2267     */
2268    /* op vA, vB, field@CCCC */
2269    mov     r0, rINST, lsr #12          @ r0<- B
2270    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2271    FETCH(r1, 1)                        @ r1<- field ref CCCC
2272    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2273    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2274    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2275    cmp     r0, #0                      @ is resolved entry null?
2276    bne     .LOP_IGET_finish          @ no, already resolved
22778:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2278    EXPORT_PC()                         @ resolve() could throw
2279    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2280    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2281    cmp     r0, #0
2282    bne     .LOP_IGET_finish
2283    b       common_exceptionThrown
2284
2285/* ------------------------------ */
2286    .balign 64
2287.L_OP_IGET_WIDE: /* 0x53 */
2288/* File: armv5te/OP_IGET_WIDE.S */
2289    /*
2290     * Wide 32-bit instance field get.
2291     */
2292    /* iget-wide vA, vB, field@CCCC */
2293    mov     r0, rINST, lsr #12          @ r0<- B
2294    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2295    FETCH(r1, 1)                        @ r1<- field ref CCCC
2296    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2297    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2298    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2299    cmp     r0, #0                      @ is resolved entry null?
2300    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
23018:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2302    EXPORT_PC()                         @ resolve() could throw
2303    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2304    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2305    cmp     r0, #0
2306    bne     .LOP_IGET_WIDE_finish
2307    b       common_exceptionThrown
2308
2309/* ------------------------------ */
2310    .balign 64
2311.L_OP_IGET_OBJECT: /* 0x54 */
2312/* File: armv5te/OP_IGET_OBJECT.S */
2313/* File: armv5te/OP_IGET.S */
2314    /*
2315     * General 32-bit instance field get.
2316     *
2317     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2318     */
2319    /* op vA, vB, field@CCCC */
2320    mov     r0, rINST, lsr #12          @ r0<- B
2321    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2322    FETCH(r1, 1)                        @ r1<- field ref CCCC
2323    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2324    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2325    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2326    cmp     r0, #0                      @ is resolved entry null?
2327    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
23288:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2329    EXPORT_PC()                         @ resolve() could throw
2330    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2331    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2332    cmp     r0, #0
2333    bne     .LOP_IGET_OBJECT_finish
2334    b       common_exceptionThrown
2335
2336
2337/* ------------------------------ */
2338    .balign 64
2339.L_OP_IGET_BOOLEAN: /* 0x55 */
2340/* File: armv5te/OP_IGET_BOOLEAN.S */
2341@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2342/* File: armv5te/OP_IGET.S */
2343    /*
2344     * General 32-bit instance field get.
2345     *
2346     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2347     */
2348    /* op vA, vB, field@CCCC */
2349    mov     r0, rINST, lsr #12          @ r0<- B
2350    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2351    FETCH(r1, 1)                        @ r1<- field ref CCCC
2352    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2353    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2354    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2355    cmp     r0, #0                      @ is resolved entry null?
2356    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
23578:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2358    EXPORT_PC()                         @ resolve() could throw
2359    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2360    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2361    cmp     r0, #0
2362    bne     .LOP_IGET_BOOLEAN_finish
2363    b       common_exceptionThrown
2364
2365
2366/* ------------------------------ */
2367    .balign 64
2368.L_OP_IGET_BYTE: /* 0x56 */
2369/* File: armv5te/OP_IGET_BYTE.S */
2370@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2371/* File: armv5te/OP_IGET.S */
2372    /*
2373     * General 32-bit instance field get.
2374     *
2375     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2376     */
2377    /* op vA, vB, field@CCCC */
2378    mov     r0, rINST, lsr #12          @ r0<- B
2379    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2380    FETCH(r1, 1)                        @ r1<- field ref CCCC
2381    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2382    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2383    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2384    cmp     r0, #0                      @ is resolved entry null?
2385    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
23868:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2387    EXPORT_PC()                         @ resolve() could throw
2388    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2389    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2390    cmp     r0, #0
2391    bne     .LOP_IGET_BYTE_finish
2392    b       common_exceptionThrown
2393
2394
2395/* ------------------------------ */
2396    .balign 64
2397.L_OP_IGET_CHAR: /* 0x57 */
2398/* File: armv5te/OP_IGET_CHAR.S */
2399@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2400/* File: armv5te/OP_IGET.S */
2401    /*
2402     * General 32-bit instance field get.
2403     *
2404     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2405     */
2406    /* op vA, vB, field@CCCC */
2407    mov     r0, rINST, lsr #12          @ r0<- B
2408    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2409    FETCH(r1, 1)                        @ r1<- field ref CCCC
2410    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2411    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2412    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2413    cmp     r0, #0                      @ is resolved entry null?
2414    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
24158:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2416    EXPORT_PC()                         @ resolve() could throw
2417    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2418    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2419    cmp     r0, #0
2420    bne     .LOP_IGET_CHAR_finish
2421    b       common_exceptionThrown
2422
2423
2424/* ------------------------------ */
2425    .balign 64
2426.L_OP_IGET_SHORT: /* 0x58 */
2427/* File: armv5te/OP_IGET_SHORT.S */
2428@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2429/* File: armv5te/OP_IGET.S */
2430    /*
2431     * General 32-bit instance field get.
2432     *
2433     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2434     */
2435    /* op vA, vB, field@CCCC */
2436    mov     r0, rINST, lsr #12          @ r0<- B
2437    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2438    FETCH(r1, 1)                        @ r1<- field ref CCCC
2439    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2440    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2441    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2442    cmp     r0, #0                      @ is resolved entry null?
2443    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
24448:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2445    EXPORT_PC()                         @ resolve() could throw
2446    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2447    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2448    cmp     r0, #0
2449    bne     .LOP_IGET_SHORT_finish
2450    b       common_exceptionThrown
2451
2452
2453/* ------------------------------ */
2454    .balign 64
2455.L_OP_IPUT: /* 0x59 */
2456/* File: armv5te/OP_IPUT.S */
2457    /*
2458     * General 32-bit instance field put.
2459     *
2460     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2461     */
2462    /* op vA, vB, field@CCCC */
2463    mov     r0, rINST, lsr #12          @ r0<- B
2464    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2465    FETCH(r1, 1)                        @ r1<- field ref CCCC
2466    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2467    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2468    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2469    cmp     r0, #0                      @ is resolved entry null?
2470    bne     .LOP_IPUT_finish          @ no, already resolved
24718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2472    EXPORT_PC()                         @ resolve() could throw
2473    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2474    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2475    cmp     r0, #0                      @ success?
2476    bne     .LOP_IPUT_finish          @ yes, finish up
2477    b       common_exceptionThrown
2478
2479/* ------------------------------ */
2480    .balign 64
2481.L_OP_IPUT_WIDE: /* 0x5a */
2482/* File: armv5te/OP_IPUT_WIDE.S */
2483    /* iput-wide vA, vB, field@CCCC */
2484    mov     r0, rINST, lsr #12          @ r0<- B
2485    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2486    FETCH(r1, 1)                        @ r1<- field ref CCCC
2487    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2488    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2489    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2490    cmp     r0, #0                      @ is resolved entry null?
2491    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
24928:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2493    EXPORT_PC()                         @ resolve() could throw
2494    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2495    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2496    cmp     r0, #0                      @ success?
2497    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2498    b       common_exceptionThrown
2499
2500/* ------------------------------ */
2501    .balign 64
2502.L_OP_IPUT_OBJECT: /* 0x5b */
2503/* File: armv5te/OP_IPUT_OBJECT.S */
2504/* File: armv5te/OP_IPUT.S */
2505    /*
2506     * General 32-bit instance field put.
2507     *
2508     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2509     */
2510    /* op vA, vB, field@CCCC */
2511    mov     r0, rINST, lsr #12          @ r0<- B
2512    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2513    FETCH(r1, 1)                        @ r1<- field ref CCCC
2514    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2515    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2516    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2517    cmp     r0, #0                      @ is resolved entry null?
2518    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
25198:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2520    EXPORT_PC()                         @ resolve() could throw
2521    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2522    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2523    cmp     r0, #0                      @ success?
2524    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2525    b       common_exceptionThrown
2526
2527
2528/* ------------------------------ */
2529    .balign 64
2530.L_OP_IPUT_BOOLEAN: /* 0x5c */
2531/* File: armv5te/OP_IPUT_BOOLEAN.S */
2532@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2533/* File: armv5te/OP_IPUT.S */
2534    /*
2535     * General 32-bit instance field put.
2536     *
2537     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2538     */
2539    /* op vA, vB, field@CCCC */
2540    mov     r0, rINST, lsr #12          @ r0<- B
2541    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2542    FETCH(r1, 1)                        @ r1<- field ref CCCC
2543    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2544    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2545    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2546    cmp     r0, #0                      @ is resolved entry null?
2547    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
25488:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2549    EXPORT_PC()                         @ resolve() could throw
2550    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2551    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2552    cmp     r0, #0                      @ success?
2553    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2554    b       common_exceptionThrown
2555
2556
2557/* ------------------------------ */
2558    .balign 64
2559.L_OP_IPUT_BYTE: /* 0x5d */
2560/* File: armv5te/OP_IPUT_BYTE.S */
2561@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2562/* File: armv5te/OP_IPUT.S */
2563    /*
2564     * General 32-bit instance field put.
2565     *
2566     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2567     */
2568    /* op vA, vB, field@CCCC */
2569    mov     r0, rINST, lsr #12          @ r0<- B
2570    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2571    FETCH(r1, 1)                        @ r1<- field ref CCCC
2572    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2573    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2574    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2575    cmp     r0, #0                      @ is resolved entry null?
2576    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
25778:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2578    EXPORT_PC()                         @ resolve() could throw
2579    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2580    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2581    cmp     r0, #0                      @ success?
2582    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2583    b       common_exceptionThrown
2584
2585
2586/* ------------------------------ */
2587    .balign 64
2588.L_OP_IPUT_CHAR: /* 0x5e */
2589/* File: armv5te/OP_IPUT_CHAR.S */
2590@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2591/* File: armv5te/OP_IPUT.S */
2592    /*
2593     * General 32-bit instance field put.
2594     *
2595     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2596     */
2597    /* op vA, vB, field@CCCC */
2598    mov     r0, rINST, lsr #12          @ r0<- B
2599    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2600    FETCH(r1, 1)                        @ r1<- field ref CCCC
2601    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2602    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2603    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2604    cmp     r0, #0                      @ is resolved entry null?
2605    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
26068:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2607    EXPORT_PC()                         @ resolve() could throw
2608    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2609    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2610    cmp     r0, #0                      @ success?
2611    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2612    b       common_exceptionThrown
2613
2614
2615/* ------------------------------ */
2616    .balign 64
2617.L_OP_IPUT_SHORT: /* 0x5f */
2618/* File: armv5te/OP_IPUT_SHORT.S */
2619@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2620/* File: armv5te/OP_IPUT.S */
2621    /*
2622     * General 32-bit instance field put.
2623     *
2624     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2625     */
2626    /* op vA, vB, field@CCCC */
2627    mov     r0, rINST, lsr #12          @ r0<- B
2628    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2629    FETCH(r1, 1)                        @ r1<- field ref CCCC
2630    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2631    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2632    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2633    cmp     r0, #0                      @ is resolved entry null?
2634    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
26358:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2636    EXPORT_PC()                         @ resolve() could throw
2637    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2638    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2639    cmp     r0, #0                      @ success?
2640    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2641    b       common_exceptionThrown
2642
2643
2644/* ------------------------------ */
2645    .balign 64
2646.L_OP_SGET: /* 0x60 */
2647/* File: armv5te/OP_SGET.S */
2648    /*
2649     * General 32-bit SGET handler.
2650     *
2651     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2652     */
2653    /* op vAA, field@BBBB */
2654    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2655    FETCH(r1, 1)                        @ r1<- field ref BBBB
2656    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2657    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2658    cmp     r0, #0                      @ is resolved entry null?
2659    beq     .LOP_SGET_resolve         @ yes, do resolve
2660.LOP_SGET_finish: @ field ptr in r0
2661    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2662    mov     r2, rINST, lsr #8           @ r2<- AA
2663    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2664    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2665    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2666    GOTO_OPCODE(ip)                     @ jump to next instruction
2667
2668/* ------------------------------ */
2669    .balign 64
2670.L_OP_SGET_WIDE: /* 0x61 */
2671/* File: armv5te/OP_SGET_WIDE.S */
2672    /*
2673     * 64-bit SGET handler.
2674     */
2675    /* sget-wide vAA, field@BBBB */
2676    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2677    FETCH(r1, 1)                        @ r1<- field ref BBBB
2678    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2679    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2680    cmp     r0, #0                      @ is resolved entry null?
2681    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2682.LOP_SGET_WIDE_finish:
2683    mov     r1, rINST, lsr #8           @ r1<- AA
2684    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2685    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2686    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2687    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2689    GOTO_OPCODE(ip)                     @ jump to next instruction
2690
2691/* ------------------------------ */
2692    .balign 64
2693.L_OP_SGET_OBJECT: /* 0x62 */
2694/* File: armv5te/OP_SGET_OBJECT.S */
2695/* File: armv5te/OP_SGET.S */
2696    /*
2697     * General 32-bit SGET handler.
2698     *
2699     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2700     */
2701    /* op vAA, field@BBBB */
2702    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2703    FETCH(r1, 1)                        @ r1<- field ref BBBB
2704    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2705    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2706    cmp     r0, #0                      @ is resolved entry null?
2707    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2708.LOP_SGET_OBJECT_finish: @ field ptr in r0
2709    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2710    mov     r2, rINST, lsr #8           @ r2<- AA
2711    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2712    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2713    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2714    GOTO_OPCODE(ip)                     @ jump to next instruction
2715
2716
2717/* ------------------------------ */
2718    .balign 64
2719.L_OP_SGET_BOOLEAN: /* 0x63 */
2720/* File: armv5te/OP_SGET_BOOLEAN.S */
2721/* File: armv5te/OP_SGET.S */
2722    /*
2723     * General 32-bit SGET handler.
2724     *
2725     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2726     */
2727    /* op vAA, field@BBBB */
2728    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2729    FETCH(r1, 1)                        @ r1<- field ref BBBB
2730    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2731    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2732    cmp     r0, #0                      @ is resolved entry null?
2733    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2734.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2735    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2736    mov     r2, rINST, lsr #8           @ r2<- AA
2737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2738    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2739    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2740    GOTO_OPCODE(ip)                     @ jump to next instruction
2741
2742
2743/* ------------------------------ */
2744    .balign 64
2745.L_OP_SGET_BYTE: /* 0x64 */
2746/* File: armv5te/OP_SGET_BYTE.S */
2747/* File: armv5te/OP_SGET.S */
2748    /*
2749     * General 32-bit SGET handler.
2750     *
2751     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2752     */
2753    /* op vAA, field@BBBB */
2754    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2755    FETCH(r1, 1)                        @ r1<- field ref BBBB
2756    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2757    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2758    cmp     r0, #0                      @ is resolved entry null?
2759    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2760.LOP_SGET_BYTE_finish: @ field ptr in r0
2761    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2762    mov     r2, rINST, lsr #8           @ r2<- AA
2763    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2764    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2765    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2766    GOTO_OPCODE(ip)                     @ jump to next instruction
2767
2768
2769/* ------------------------------ */
2770    .balign 64
2771.L_OP_SGET_CHAR: /* 0x65 */
2772/* File: armv5te/OP_SGET_CHAR.S */
2773/* File: armv5te/OP_SGET.S */
2774    /*
2775     * General 32-bit SGET handler.
2776     *
2777     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2778     */
2779    /* op vAA, field@BBBB */
2780    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2781    FETCH(r1, 1)                        @ r1<- field ref BBBB
2782    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2783    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2784    cmp     r0, #0                      @ is resolved entry null?
2785    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2786.LOP_SGET_CHAR_finish: @ field ptr in r0
2787    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2788    mov     r2, rINST, lsr #8           @ r2<- AA
2789    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2790    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2792    GOTO_OPCODE(ip)                     @ jump to next instruction
2793
2794
2795/* ------------------------------ */
2796    .balign 64
2797.L_OP_SGET_SHORT: /* 0x66 */
2798/* File: armv5te/OP_SGET_SHORT.S */
2799/* File: armv5te/OP_SGET.S */
2800    /*
2801     * General 32-bit SGET handler.
2802     *
2803     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2804     */
2805    /* op vAA, field@BBBB */
2806    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2807    FETCH(r1, 1)                        @ r1<- field ref BBBB
2808    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2809    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2810    cmp     r0, #0                      @ is resolved entry null?
2811    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2812.LOP_SGET_SHORT_finish: @ field ptr in r0
2813    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2814    mov     r2, rINST, lsr #8           @ r2<- AA
2815    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2816    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2817    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2818    GOTO_OPCODE(ip)                     @ jump to next instruction
2819
2820
2821/* ------------------------------ */
2822    .balign 64
2823.L_OP_SPUT: /* 0x67 */
2824/* File: armv5te/OP_SPUT.S */
2825    /*
2826     * General 32-bit SPUT handler.
2827     *
2828     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2829     */
2830    /* op vAA, field@BBBB */
2831    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2832    FETCH(r1, 1)                        @ r1<- field ref BBBB
2833    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2834    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2835    cmp     r0, #0                      @ is resolved entry null?
2836    beq     .LOP_SPUT_resolve         @ yes, do resolve
2837.LOP_SPUT_finish:   @ field ptr in r0
2838    mov     r2, rINST, lsr #8           @ r2<- AA
2839    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2840    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2842    str     r1, [r0, #offStaticField_value] @ field<- vAA
2843    GOTO_OPCODE(ip)                     @ jump to next instruction
2844
2845/* ------------------------------ */
2846    .balign 64
2847.L_OP_SPUT_WIDE: /* 0x68 */
2848/* File: armv5te/OP_SPUT_WIDE.S */
2849    /*
2850     * 64-bit SPUT handler.
2851     */
2852    /* sput-wide vAA, field@BBBB */
2853    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2854    FETCH(r1, 1)                        @ r1<- field ref BBBB
2855    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2856    mov     r9, rINST, lsr #8           @ r9<- AA
2857    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2859    cmp     r0, #0                      @ is resolved entry null?
2860    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2861.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
2862    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2863    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
2864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2865    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
2866    GOTO_OPCODE(ip)                     @ jump to next instruction
2867
2868/* ------------------------------ */
2869    .balign 64
2870.L_OP_SPUT_OBJECT: /* 0x69 */
2871/* File: armv5te/OP_SPUT_OBJECT.S */
2872/* File: armv5te/OP_SPUT.S */
2873    /*
2874     * General 32-bit SPUT handler.
2875     *
2876     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2877     */
2878    /* op vAA, field@BBBB */
2879    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2880    FETCH(r1, 1)                        @ r1<- field ref BBBB
2881    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2882    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2883    cmp     r0, #0                      @ is resolved entry null?
2884    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
2885.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
2886    mov     r2, rINST, lsr #8           @ r2<- AA
2887    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2888    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2890    str     r1, [r0, #offStaticField_value] @ field<- vAA
2891    GOTO_OPCODE(ip)                     @ jump to next instruction
2892
2893
2894/* ------------------------------ */
2895    .balign 64
2896.L_OP_SPUT_BOOLEAN: /* 0x6a */
2897/* File: armv5te/OP_SPUT_BOOLEAN.S */
2898/* File: armv5te/OP_SPUT.S */
2899    /*
2900     * General 32-bit SPUT handler.
2901     *
2902     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2903     */
2904    /* op vAA, field@BBBB */
2905    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2906    FETCH(r1, 1)                        @ r1<- field ref BBBB
2907    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2908    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2909    cmp     r0, #0                      @ is resolved entry null?
2910    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
2911.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
2912    mov     r2, rINST, lsr #8           @ r2<- AA
2913    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2914    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2916    str     r1, [r0, #offStaticField_value] @ field<- vAA
2917    GOTO_OPCODE(ip)                     @ jump to next instruction
2918
2919
2920/* ------------------------------ */
2921    .balign 64
2922.L_OP_SPUT_BYTE: /* 0x6b */
2923/* File: armv5te/OP_SPUT_BYTE.S */
2924/* File: armv5te/OP_SPUT.S */
2925    /*
2926     * General 32-bit SPUT handler.
2927     *
2928     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2929     */
2930    /* op vAA, field@BBBB */
2931    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2932    FETCH(r1, 1)                        @ r1<- field ref BBBB
2933    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2934    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2935    cmp     r0, #0                      @ is resolved entry null?
2936    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
2937.LOP_SPUT_BYTE_finish:   @ field ptr in r0
2938    mov     r2, rINST, lsr #8           @ r2<- AA
2939    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2940    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2941    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2942    str     r1, [r0, #offStaticField_value] @ field<- vAA
2943    GOTO_OPCODE(ip)                     @ jump to next instruction
2944
2945
2946/* ------------------------------ */
2947    .balign 64
2948.L_OP_SPUT_CHAR: /* 0x6c */
2949/* File: armv5te/OP_SPUT_CHAR.S */
2950/* File: armv5te/OP_SPUT.S */
2951    /*
2952     * General 32-bit SPUT handler.
2953     *
2954     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2955     */
2956    /* op vAA, field@BBBB */
2957    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2958    FETCH(r1, 1)                        @ r1<- field ref BBBB
2959    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2960    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2961    cmp     r0, #0                      @ is resolved entry null?
2962    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
2963.LOP_SPUT_CHAR_finish:   @ field ptr in r0
2964    mov     r2, rINST, lsr #8           @ r2<- AA
2965    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2966    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2968    str     r1, [r0, #offStaticField_value] @ field<- vAA
2969    GOTO_OPCODE(ip)                     @ jump to next instruction
2970
2971
2972/* ------------------------------ */
2973    .balign 64
2974.L_OP_SPUT_SHORT: /* 0x6d */
2975/* File: armv5te/OP_SPUT_SHORT.S */
2976/* File: armv5te/OP_SPUT.S */
2977    /*
2978     * General 32-bit SPUT handler.
2979     *
2980     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2981     */
2982    /* op vAA, field@BBBB */
2983    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2984    FETCH(r1, 1)                        @ r1<- field ref BBBB
2985    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2986    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2987    cmp     r0, #0                      @ is resolved entry null?
2988    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
2989.LOP_SPUT_SHORT_finish:   @ field ptr in r0
2990    mov     r2, rINST, lsr #8           @ r2<- AA
2991    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2992    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2993    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2994    str     r1, [r0, #offStaticField_value] @ field<- vAA
2995    GOTO_OPCODE(ip)                     @ jump to next instruction
2996
2997
2998/* ------------------------------ */
2999    .balign 64
3000.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3001/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3002    /*
3003     * Handle a virtual method call.
3004     *
3005     * for: invoke-virtual, invoke-virtual/range
3006     */
3007    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3008    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3009    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3010    FETCH(r1, 1)                        @ r1<- BBBB
3011    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3012    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3013    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3014    .if     (!0)
3015    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3016    .endif
3017    cmp     r0, #0                      @ already resolved?
3018    EXPORT_PC()                         @ must export for invoke
3019    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3020    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3021    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3022    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3023    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3024    cmp     r0, #0                      @ got null?
3025    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3026    b       common_exceptionThrown      @ yes, handle exception
3027
3028/* ------------------------------ */
3029    .balign 64
3030.L_OP_INVOKE_SUPER: /* 0x6f */
3031/* File: armv5te/OP_INVOKE_SUPER.S */
3032    /*
3033     * Handle a "super" method call.
3034     *
3035     * for: invoke-super, invoke-super/range
3036     */
3037    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3038    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3039    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3040    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3041    .if     (!0)
3042    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3043    .endif
3044    FETCH(r1, 1)                        @ r1<- BBBB
3045    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3046    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3047    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3048    cmp     r2, #0                      @ null "this"?
3049    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3050    beq     common_errNullObject        @ null "this", throw exception
3051    cmp     r0, #0                      @ already resolved?
3052    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3053    EXPORT_PC()                         @ must export for invoke
3054    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3055    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3056
3057/* ------------------------------ */
3058    .balign 64
3059.L_OP_INVOKE_DIRECT: /* 0x70 */
3060/* File: armv5te/OP_INVOKE_DIRECT.S */
3061    /*
3062     * Handle a direct method call.
3063     *
3064     * (We could defer the "is 'this' pointer null" test to the common
3065     * method invocation code, and use a flag to indicate that static
3066     * calls don't count.  If we do this as part of copying the arguments
3067     * out we could avoiding loading the first arg twice.)
3068     *
3069     * for: invoke-direct, invoke-direct/range
3070     */
3071    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3072    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3073    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3074    FETCH(r1, 1)                        @ r1<- BBBB
3075    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3076    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3077    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3078    .if     (!0)
3079    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3080    .endif
3081    cmp     r0, #0                      @ already resolved?
3082    EXPORT_PC()                         @ must export for invoke
3083    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3084    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3085.LOP_INVOKE_DIRECT_finish:
3086    cmp     r2, #0                      @ null "this" ref?
3087    bne     common_invokeMethodNoRange   @ no, continue on
3088    b       common_errNullObject        @ yes, throw exception
3089
3090/* ------------------------------ */
3091    .balign 64
3092.L_OP_INVOKE_STATIC: /* 0x71 */
3093/* File: armv5te/OP_INVOKE_STATIC.S */
3094    /*
3095     * Handle a static method call.
3096     *
3097     * for: invoke-static, invoke-static/range
3098     */
3099    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3100    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3101    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3102    FETCH(r1, 1)                        @ r1<- BBBB
3103    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3104    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3105    cmp     r0, #0                      @ already resolved?
3106    EXPORT_PC()                         @ must export for invoke
3107    bne     common_invokeMethodNoRange @ yes, continue on
31080:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3109    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3110    mov     r2, #METHOD_STATIC          @ resolver method type
3111    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3112    cmp     r0, #0                      @ got null?
3113    bne     common_invokeMethodNoRange @ no, continue
3114    b       common_exceptionThrown      @ yes, handle exception
3115
3116
3117/* ------------------------------ */
3118    .balign 64
3119.L_OP_INVOKE_INTERFACE: /* 0x72 */
3120/* File: armv5te/OP_INVOKE_INTERFACE.S */
3121    /*
3122     * Handle an interface method call.
3123     *
3124     * for: invoke-interface, invoke-interface/range
3125     */
3126    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3127    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3128    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3129    FETCH(r1, 1)                        @ r1<- BBBB
3130    .if     (!0)
3131    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3132    .endif
3133    EXPORT_PC()                         @ must export for invoke
3134    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3135    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3136    cmp     r0, #0                      @ null obj?
3137    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3138    beq     common_errNullObject        @ yes, fail
3139    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3140    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3141    cmp     r0, #0                      @ failed?
3142    beq     common_exceptionThrown      @ yes, handle exception
3143    b       common_invokeMethodNoRange @ jump to common handler
3144
3145
3146/* ------------------------------ */
3147    .balign 64
3148.L_OP_UNUSED_73: /* 0x73 */
3149/* File: armv5te/OP_UNUSED_73.S */
3150/* File: armv5te/unused.S */
3151    bl      common_abort
3152
3153
3154
3155/* ------------------------------ */
3156    .balign 64
3157.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3158/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3159/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3160    /*
3161     * Handle a virtual method call.
3162     *
3163     * for: invoke-virtual, invoke-virtual/range
3164     */
3165    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3166    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3167    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3168    FETCH(r1, 1)                        @ r1<- BBBB
3169    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3170    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3171    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3172    .if     (!1)
3173    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3174    .endif
3175    cmp     r0, #0                      @ already resolved?
3176    EXPORT_PC()                         @ must export for invoke
3177    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3178    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3179    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3180    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3181    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3182    cmp     r0, #0                      @ got null?
3183    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3184    b       common_exceptionThrown      @ yes, handle exception
3185
3186
3187/* ------------------------------ */
3188    .balign 64
3189.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3190/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3191/* File: armv5te/OP_INVOKE_SUPER.S */
3192    /*
3193     * Handle a "super" method call.
3194     *
3195     * for: invoke-super, invoke-super/range
3196     */
3197    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3198    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3199    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3200    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3201    .if     (!1)
3202    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3203    .endif
3204    FETCH(r1, 1)                        @ r1<- BBBB
3205    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3206    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3207    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3208    cmp     r2, #0                      @ null "this"?
3209    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3210    beq     common_errNullObject        @ null "this", throw exception
3211    cmp     r0, #0                      @ already resolved?
3212    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3213    EXPORT_PC()                         @ must export for invoke
3214    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3215    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3216
3217
3218/* ------------------------------ */
3219    .balign 64
3220.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3221/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3222/* File: armv5te/OP_INVOKE_DIRECT.S */
3223    /*
3224     * Handle a direct method call.
3225     *
3226     * (We could defer the "is 'this' pointer null" test to the common
3227     * method invocation code, and use a flag to indicate that static
3228     * calls don't count.  If we do this as part of copying the arguments
3229     * out we could avoiding loading the first arg twice.)
3230     *
3231     * for: invoke-direct, invoke-direct/range
3232     */
3233    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3234    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3235    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3236    FETCH(r1, 1)                        @ r1<- BBBB
3237    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3238    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3239    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3240    .if     (!1)
3241    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3242    .endif
3243    cmp     r0, #0                      @ already resolved?
3244    EXPORT_PC()                         @ must export for invoke
3245    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3246    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3247.LOP_INVOKE_DIRECT_RANGE_finish:
3248    cmp     r2, #0                      @ null "this" ref?
3249    bne     common_invokeMethodRange   @ no, continue on
3250    b       common_errNullObject        @ yes, throw exception
3251
3252
3253/* ------------------------------ */
3254    .balign 64
3255.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3256/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3257/* File: armv5te/OP_INVOKE_STATIC.S */
3258    /*
3259     * Handle a static method call.
3260     *
3261     * for: invoke-static, invoke-static/range
3262     */
3263    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3264    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3265    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3266    FETCH(r1, 1)                        @ r1<- BBBB
3267    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3268    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3269    cmp     r0, #0                      @ already resolved?
3270    EXPORT_PC()                         @ must export for invoke
3271    bne     common_invokeMethodRange @ yes, continue on
32720:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3273    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3274    mov     r2, #METHOD_STATIC          @ resolver method type
3275    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3276    cmp     r0, #0                      @ got null?
3277    bne     common_invokeMethodRange @ no, continue
3278    b       common_exceptionThrown      @ yes, handle exception
3279
3280
3281
3282/* ------------------------------ */
3283    .balign 64
3284.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3285/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3286/* File: armv5te/OP_INVOKE_INTERFACE.S */
3287    /*
3288     * Handle an interface method call.
3289     *
3290     * for: invoke-interface, invoke-interface/range
3291     */
3292    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3293    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3294    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3295    FETCH(r1, 1)                        @ r1<- BBBB
3296    .if     (!1)
3297    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3298    .endif
3299    EXPORT_PC()                         @ must export for invoke
3300    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3301    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3302    cmp     r0, #0                      @ null obj?
3303    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3304    beq     common_errNullObject        @ yes, fail
3305    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3306    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3307    cmp     r0, #0                      @ failed?
3308    beq     common_exceptionThrown      @ yes, handle exception
3309    b       common_invokeMethodRange @ jump to common handler
3310
3311
3312
3313/* ------------------------------ */
3314    .balign 64
3315.L_OP_UNUSED_79: /* 0x79 */
3316/* File: armv5te/OP_UNUSED_79.S */
3317/* File: armv5te/unused.S */
3318    bl      common_abort
3319
3320
3321
3322/* ------------------------------ */
3323    .balign 64
3324.L_OP_UNUSED_7A: /* 0x7a */
3325/* File: armv5te/OP_UNUSED_7A.S */
3326/* File: armv5te/unused.S */
3327    bl      common_abort
3328
3329
3330
3331/* ------------------------------ */
3332    .balign 64
3333.L_OP_NEG_INT: /* 0x7b */
3334/* File: armv5te/OP_NEG_INT.S */
3335/* File: armv5te/unop.S */
3336    /*
3337     * Generic 32-bit unary operation.  Provide an "instr" line that
3338     * specifies an instruction that performs "result = op r0".
3339     * This could be an ARM instruction or a function call.
3340     *
3341     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3342     *      int-to-byte, int-to-char, int-to-short
3343     */
3344    /* unop vA, vB */
3345    mov     r3, rINST, lsr #12          @ r3<- B
3346    mov     r9, rINST, lsr #8           @ r9<- A+
3347    GET_VREG(r0, r3)                    @ r0<- vB
3348    and     r9, r9, #15
3349                               @ optional op; may set condition codes
3350    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3351    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3353    SET_VREG(r0, r9)                    @ vAA<- r0
3354    GOTO_OPCODE(ip)                     @ jump to next instruction
3355    /* 9-10 instructions */
3356
3357
3358/* ------------------------------ */
3359    .balign 64
3360.L_OP_NOT_INT: /* 0x7c */
3361/* File: armv5te/OP_NOT_INT.S */
3362/* File: armv5te/unop.S */
3363    /*
3364     * Generic 32-bit unary operation.  Provide an "instr" line that
3365     * specifies an instruction that performs "result = op r0".
3366     * This could be an ARM instruction or a function call.
3367     *
3368     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3369     *      int-to-byte, int-to-char, int-to-short
3370     */
3371    /* unop vA, vB */
3372    mov     r3, rINST, lsr #12          @ r3<- B
3373    mov     r9, rINST, lsr #8           @ r9<- A+
3374    GET_VREG(r0, r3)                    @ r0<- vB
3375    and     r9, r9, #15
3376                               @ optional op; may set condition codes
3377    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3378    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3379    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3380    SET_VREG(r0, r9)                    @ vAA<- r0
3381    GOTO_OPCODE(ip)                     @ jump to next instruction
3382    /* 9-10 instructions */
3383
3384
3385/* ------------------------------ */
3386    .balign 64
3387.L_OP_NEG_LONG: /* 0x7d */
3388/* File: armv5te/OP_NEG_LONG.S */
3389/* File: armv5te/unopWide.S */
3390    /*
3391     * Generic 64-bit unary operation.  Provide an "instr" line that
3392     * specifies an instruction that performs "result = op r0/r1".
3393     * This could be an ARM instruction or a function call.
3394     *
3395     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3396     */
3397    /* unop vA, vB */
3398    mov     r9, rINST, lsr #8           @ r9<- A+
3399    mov     r3, rINST, lsr #12          @ r3<- B
3400    and     r9, r9, #15
3401    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3402    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3403    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3404    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3405    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3406    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3407    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3408    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3409    GOTO_OPCODE(ip)                     @ jump to next instruction
3410    /* 12-13 instructions */
3411
3412
3413
3414/* ------------------------------ */
3415    .balign 64
3416.L_OP_NOT_LONG: /* 0x7e */
3417/* File: armv5te/OP_NOT_LONG.S */
3418/* File: armv5te/unopWide.S */
3419    /*
3420     * Generic 64-bit unary operation.  Provide an "instr" line that
3421     * specifies an instruction that performs "result = op r0/r1".
3422     * This could be an ARM instruction or a function call.
3423     *
3424     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3425     */
3426    /* unop vA, vB */
3427    mov     r9, rINST, lsr #8           @ r9<- A+
3428    mov     r3, rINST, lsr #12          @ r3<- B
3429    and     r9, r9, #15
3430    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3431    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3432    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3433    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3434    mvn     r0, r0                           @ optional op; may set condition codes
3435    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3436    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3437    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3438    GOTO_OPCODE(ip)                     @ jump to next instruction
3439    /* 12-13 instructions */
3440
3441
3442
3443/* ------------------------------ */
3444    .balign 64
3445.L_OP_NEG_FLOAT: /* 0x7f */
3446/* File: armv5te/OP_NEG_FLOAT.S */
3447/* File: armv5te/unop.S */
3448    /*
3449     * Generic 32-bit unary operation.  Provide an "instr" line that
3450     * specifies an instruction that performs "result = op r0".
3451     * This could be an ARM instruction or a function call.
3452     *
3453     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3454     *      int-to-byte, int-to-char, int-to-short
3455     */
3456    /* unop vA, vB */
3457    mov     r3, rINST, lsr #12          @ r3<- B
3458    mov     r9, rINST, lsr #8           @ r9<- A+
3459    GET_VREG(r0, r3)                    @ r0<- vB
3460    and     r9, r9, #15
3461                               @ optional op; may set condition codes
3462    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3463    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3464    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3465    SET_VREG(r0, r9)                    @ vAA<- r0
3466    GOTO_OPCODE(ip)                     @ jump to next instruction
3467    /* 9-10 instructions */
3468
3469
3470/* ------------------------------ */
3471    .balign 64
3472.L_OP_NEG_DOUBLE: /* 0x80 */
3473/* File: armv5te/OP_NEG_DOUBLE.S */
3474/* File: armv5te/unopWide.S */
3475    /*
3476     * Generic 64-bit unary operation.  Provide an "instr" line that
3477     * specifies an instruction that performs "result = op r0/r1".
3478     * This could be an ARM instruction or a function call.
3479     *
3480     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3481     */
3482    /* unop vA, vB */
3483    mov     r9, rINST, lsr #8           @ r9<- A+
3484    mov     r3, rINST, lsr #12          @ r3<- B
3485    and     r9, r9, #15
3486    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3487    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3488    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3489    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3490                               @ optional op; may set condition codes
3491    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3492    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3493    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3494    GOTO_OPCODE(ip)                     @ jump to next instruction
3495    /* 12-13 instructions */
3496
3497
3498
3499/* ------------------------------ */
3500    .balign 64
3501.L_OP_INT_TO_LONG: /* 0x81 */
3502/* File: armv5te/OP_INT_TO_LONG.S */
3503/* File: armv5te/unopWider.S */
3504    /*
3505     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3506     * that specifies an instruction that performs "result = op r0", where
3507     * "result" is a 64-bit quantity in r0/r1.
3508     *
3509     * For: int-to-long, int-to-double, float-to-long, float-to-double
3510     */
3511    /* unop vA, vB */
3512    mov     r9, rINST, lsr #8           @ r9<- A+
3513    mov     r3, rINST, lsr #12          @ r3<- B
3514    and     r9, r9, #15
3515    GET_VREG(r0, r3)                    @ r0<- vB
3516    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3517                               @ optional op; may set condition codes
3518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3519    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3521    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3522    GOTO_OPCODE(ip)                     @ jump to next instruction
3523    /* 10-11 instructions */
3524
3525
3526/* ------------------------------ */
3527    .balign 64
3528.L_OP_INT_TO_FLOAT: /* 0x82 */
3529/* File: vfp/OP_INT_TO_FLOAT.S */
3530/* File: vfp/funop.S */
3531    /*
3532     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3533     * line that specifies an instruction that performs "s1 = op s0".
3534     *
3535     * for: int-to-float, float-to-int
3536     */
3537    /* unop vA, vB */
3538    mov     r3, rINST, lsr #12          @ r3<- B
3539    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3540    flds    s0, [r3]                    @ s0<- vB
3541    mov     r9, rINST, lsr #8           @ r9<- A+
3542    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3543    and     r9, r9, #15                 @ r9<- A
3544    fsitos  s1, s0                              @ s1<- op
3545    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3546    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3547    fsts    s1, [r9]                    @ vA<- s1
3548    GOTO_OPCODE(ip)                     @ jump to next instruction
3549
3550
3551/* ------------------------------ */
3552    .balign 64
3553.L_OP_INT_TO_DOUBLE: /* 0x83 */
3554/* File: vfp/OP_INT_TO_DOUBLE.S */
3555/* File: vfp/funopWider.S */
3556    /*
3557     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3558     * "instr" line that specifies an instruction that performs "d0 = op s0".
3559     *
3560     * For: int-to-double, float-to-double
3561     */
3562    /* unop vA, vB */
3563    mov     r3, rINST, lsr #12          @ r3<- B
3564    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3565    flds    s0, [r3]                    @ s0<- vB
3566    mov     r9, rINST, lsr #8           @ r9<- A+
3567    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3568    and     r9, r9, #15                 @ r9<- A
3569    fsitod  d0, s0                              @ d0<- op
3570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3571    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3572    fstd    d0, [r9]                    @ vA<- d0
3573    GOTO_OPCODE(ip)                     @ jump to next instruction
3574
3575
3576/* ------------------------------ */
3577    .balign 64
3578.L_OP_LONG_TO_INT: /* 0x84 */
3579/* File: armv5te/OP_LONG_TO_INT.S */
3580/* we ignore the high word, making this equivalent to a 32-bit reg move */
3581/* File: armv5te/OP_MOVE.S */
3582    /* for move, move-object, long-to-int */
3583    /* op vA, vB */
3584    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3585    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3586    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3587    GET_VREG(r2, r1)                    @ r2<- fp[B]
3588    and     r0, r0, #15
3589    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3590    SET_VREG(r2, r0)                    @ fp[A]<- r2
3591    GOTO_OPCODE(ip)                     @ execute next instruction
3592
3593
3594
3595/* ------------------------------ */
3596    .balign 64
3597.L_OP_LONG_TO_FLOAT: /* 0x85 */
3598/* File: armv5te/OP_LONG_TO_FLOAT.S */
3599/* File: armv5te/unopNarrower.S */
3600    /*
3601     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3602     * that specifies an instruction that performs "result = op r0/r1", where
3603     * "result" is a 32-bit quantity in r0.
3604     *
3605     * For: long-to-float, double-to-int, double-to-float
3606     *
3607     * (This would work for long-to-int, but that instruction is actually
3608     * an exact match for OP_MOVE.)
3609     */
3610    /* unop vA, vB */
3611    mov     r3, rINST, lsr #12          @ r3<- B
3612    mov     r9, rINST, lsr #8           @ r9<- A+
3613    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3614    and     r9, r9, #15
3615    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3616    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3617                               @ optional op; may set condition codes
3618    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3620    SET_VREG(r0, r9)                    @ vA<- r0
3621    GOTO_OPCODE(ip)                     @ jump to next instruction
3622    /* 10-11 instructions */
3623
3624
3625/* ------------------------------ */
3626    .balign 64
3627.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3628/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3629/* File: armv5te/unopWide.S */
3630    /*
3631     * Generic 64-bit unary operation.  Provide an "instr" line that
3632     * specifies an instruction that performs "result = op r0/r1".
3633     * This could be an ARM instruction or a function call.
3634     *
3635     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3636     */
3637    /* unop vA, vB */
3638    mov     r9, rINST, lsr #8           @ r9<- A+
3639    mov     r3, rINST, lsr #12          @ r3<- B
3640    and     r9, r9, #15
3641    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3642    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3643    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3644    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3645                               @ optional op; may set condition codes
3646    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3647    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3648    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3649    GOTO_OPCODE(ip)                     @ jump to next instruction
3650    /* 12-13 instructions */
3651
3652
3653
3654/* ------------------------------ */
3655    .balign 64
3656.L_OP_FLOAT_TO_INT: /* 0x87 */
3657/* File: vfp/OP_FLOAT_TO_INT.S */
3658/* File: vfp/funop.S */
3659    /*
3660     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3661     * line that specifies an instruction that performs "s1 = op s0".
3662     *
3663     * for: int-to-float, float-to-int
3664     */
3665    /* unop vA, vB */
3666    mov     r3, rINST, lsr #12          @ r3<- B
3667    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3668    flds    s0, [r3]                    @ s0<- vB
3669    mov     r9, rINST, lsr #8           @ r9<- A+
3670    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3671    and     r9, r9, #15                 @ r9<- A
3672    ftosizs s1, s0                              @ s1<- op
3673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3674    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3675    fsts    s1, [r9]                    @ vA<- s1
3676    GOTO_OPCODE(ip)                     @ jump to next instruction
3677
3678
3679/* ------------------------------ */
3680    .balign 64
3681.L_OP_FLOAT_TO_LONG: /* 0x88 */
3682/* File: armv5te/OP_FLOAT_TO_LONG.S */
3683@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3684/* File: armv5te/unopWider.S */
3685    /*
3686     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3687     * that specifies an instruction that performs "result = op r0", where
3688     * "result" is a 64-bit quantity in r0/r1.
3689     *
3690     * For: int-to-long, int-to-double, float-to-long, float-to-double
3691     */
3692    /* unop vA, vB */
3693    mov     r9, rINST, lsr #8           @ r9<- A+
3694    mov     r3, rINST, lsr #12          @ r3<- B
3695    and     r9, r9, #15
3696    GET_VREG(r0, r3)                    @ r0<- vB
3697    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3698                               @ optional op; may set condition codes
3699    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3700    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3701    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3702    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3703    GOTO_OPCODE(ip)                     @ jump to next instruction
3704    /* 10-11 instructions */
3705
3706
3707
3708/* ------------------------------ */
3709    .balign 64
3710.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3711/* File: vfp/OP_FLOAT_TO_DOUBLE.S */
3712/* File: vfp/funopWider.S */
3713    /*
3714     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3715     * "instr" line that specifies an instruction that performs "d0 = op s0".
3716     *
3717     * For: int-to-double, float-to-double
3718     */
3719    /* unop vA, vB */
3720    mov     r3, rINST, lsr #12          @ r3<- B
3721    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3722    flds    s0, [r3]                    @ s0<- vB
3723    mov     r9, rINST, lsr #8           @ r9<- A+
3724    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3725    and     r9, r9, #15                 @ r9<- A
3726    fcvtds  d0, s0                              @ d0<- op
3727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3728    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3729    fstd    d0, [r9]                    @ vA<- d0
3730    GOTO_OPCODE(ip)                     @ jump to next instruction
3731
3732
3733/* ------------------------------ */
3734    .balign 64
3735.L_OP_DOUBLE_TO_INT: /* 0x8a */
3736/* File: vfp/OP_DOUBLE_TO_INT.S */
3737/* File: vfp/funopNarrower.S */
3738    /*
3739     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3740     * "instr" line that specifies an instruction that performs "s0 = op d0".
3741     *
3742     * For: double-to-int, double-to-float
3743     */
3744    /* unop vA, vB */
3745    mov     r3, rINST, lsr #12          @ r3<- B
3746    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3747    fldd    d0, [r3]                    @ d0<- vB
3748    mov     r9, rINST, lsr #8           @ r9<- A+
3749    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3750    and     r9, r9, #15                 @ r9<- A
3751    ftosizd  s0, d0                              @ s0<- op
3752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3753    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3754    fsts    s0, [r9]                    @ vA<- s0
3755    GOTO_OPCODE(ip)                     @ jump to next instruction
3756
3757
3758/* ------------------------------ */
3759    .balign 64
3760.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3761/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3762@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3763/* File: armv5te/unopWide.S */
3764    /*
3765     * Generic 64-bit unary operation.  Provide an "instr" line that
3766     * specifies an instruction that performs "result = op r0/r1".
3767     * This could be an ARM instruction or a function call.
3768     *
3769     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3770     */
3771    /* unop vA, vB */
3772    mov     r9, rINST, lsr #8           @ r9<- A+
3773    mov     r3, rINST, lsr #12          @ r3<- B
3774    and     r9, r9, #15
3775    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3776    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3777    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3778    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3779                               @ optional op; may set condition codes
3780    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3781    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3782    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3783    GOTO_OPCODE(ip)                     @ jump to next instruction
3784    /* 12-13 instructions */
3785
3786
3787
3788
3789/* ------------------------------ */
3790    .balign 64
3791.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3792/* File: vfp/OP_DOUBLE_TO_FLOAT.S */
3793/* File: vfp/funopNarrower.S */
3794    /*
3795     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3796     * "instr" line that specifies an instruction that performs "s0 = op d0".
3797     *
3798     * For: double-to-int, double-to-float
3799     */
3800    /* unop vA, vB */
3801    mov     r3, rINST, lsr #12          @ r3<- B
3802    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3803    fldd    d0, [r3]                    @ d0<- vB
3804    mov     r9, rINST, lsr #8           @ r9<- A+
3805    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3806    and     r9, r9, #15                 @ r9<- A
3807    fcvtsd  s0, d0                              @ s0<- op
3808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3809    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3810    fsts    s0, [r9]                    @ vA<- s0
3811    GOTO_OPCODE(ip)                     @ jump to next instruction
3812
3813
3814/* ------------------------------ */
3815    .balign 64
3816.L_OP_INT_TO_BYTE: /* 0x8d */
3817/* File: armv5te/OP_INT_TO_BYTE.S */
3818/* File: armv5te/unop.S */
3819    /*
3820     * Generic 32-bit unary operation.  Provide an "instr" line that
3821     * specifies an instruction that performs "result = op r0".
3822     * This could be an ARM instruction or a function call.
3823     *
3824     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3825     *      int-to-byte, int-to-char, int-to-short
3826     */
3827    /* unop vA, vB */
3828    mov     r3, rINST, lsr #12          @ r3<- B
3829    mov     r9, rINST, lsr #8           @ r9<- A+
3830    GET_VREG(r0, r3)                    @ r0<- vB
3831    and     r9, r9, #15
3832    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3833    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3834    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3835    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3836    SET_VREG(r0, r9)                    @ vAA<- r0
3837    GOTO_OPCODE(ip)                     @ jump to next instruction
3838    /* 9-10 instructions */
3839
3840
3841/* ------------------------------ */
3842    .balign 64
3843.L_OP_INT_TO_CHAR: /* 0x8e */
3844/* File: armv5te/OP_INT_TO_CHAR.S */
3845/* File: armv5te/unop.S */
3846    /*
3847     * Generic 32-bit unary operation.  Provide an "instr" line that
3848     * specifies an instruction that performs "result = op r0".
3849     * This could be an ARM instruction or a function call.
3850     *
3851     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3852     *      int-to-byte, int-to-char, int-to-short
3853     */
3854    /* unop vA, vB */
3855    mov     r3, rINST, lsr #12          @ r3<- B
3856    mov     r9, rINST, lsr #8           @ r9<- A+
3857    GET_VREG(r0, r3)                    @ r0<- vB
3858    and     r9, r9, #15
3859    mov     r0, r0, asl #16                           @ optional op; may set condition codes
3860    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3861    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
3862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3863    SET_VREG(r0, r9)                    @ vAA<- r0
3864    GOTO_OPCODE(ip)                     @ jump to next instruction
3865    /* 9-10 instructions */
3866
3867
3868/* ------------------------------ */
3869    .balign 64
3870.L_OP_INT_TO_SHORT: /* 0x8f */
3871/* File: armv5te/OP_INT_TO_SHORT.S */
3872/* File: armv5te/unop.S */
3873    /*
3874     * Generic 32-bit unary operation.  Provide an "instr" line that
3875     * specifies an instruction that performs "result = op r0".
3876     * This could be an ARM instruction or a function call.
3877     *
3878     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3879     *      int-to-byte, int-to-char, int-to-short
3880     */
3881    /* unop vA, vB */
3882    mov     r3, rINST, lsr #12          @ r3<- B
3883    mov     r9, rINST, lsr #8           @ r9<- A+
3884    GET_VREG(r0, r3)                    @ r0<- vB
3885    and     r9, r9, #15
3886    mov     r0, r0, asl #16                           @ optional op; may set condition codes
3887    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3888    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
3889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3890    SET_VREG(r0, r9)                    @ vAA<- r0
3891    GOTO_OPCODE(ip)                     @ jump to next instruction
3892    /* 9-10 instructions */
3893
3894
3895/* ------------------------------ */
3896    .balign 64
3897.L_OP_ADD_INT: /* 0x90 */
3898/* File: armv5te/OP_ADD_INT.S */
3899/* File: armv5te/binop.S */
3900    /*
3901     * Generic 32-bit binary operation.  Provide an "instr" line that
3902     * specifies an instruction that performs "result = r0 op r1".
3903     * This could be an ARM instruction or a function call.  (If the result
3904     * comes back in a register other than r0, you can override "result".)
3905     *
3906     * If "chkzero" is set to 1, we perform a divide-by-zero check on
3907     * vCC (r1).  Useful for integer division and modulus.  Note that we
3908     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
3909     * handles it correctly.
3910     *
3911     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
3912     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
3913     *      mul-float, div-float, rem-float
3914     */
3915    /* binop vAA, vBB, vCC */
3916    FETCH(r0, 1)                        @ r0<- CCBB
3917    mov     r9, rINST, lsr #8           @ r9<- AA
3918    mov     r3, r0, lsr #8              @ r3<- CC
3919    and     r2, r0, #255                @ r2<- BB
3920    GET_VREG(r1, r3)                    @ r1<- vCC
3921    GET_VREG(r0, r2)                    @ r0<- vBB
3922    .if 0
3923    cmp     r1, #0                      @ is second operand zero?
3924    beq     common_errDivideByZero
3925    .endif
3926
3927    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3928                               @ optional op; may set condition codes
3929    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
3930    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3931    SET_VREG(r0, r9)               @ vAA<- r0
3932    GOTO_OPCODE(ip)                     @ jump to next instruction
3933    /* 11-14 instructions */
3934
3935
3936
3937/* ------------------------------ */
3938    .balign 64
3939.L_OP_SUB_INT: /* 0x91 */
3940/* File: armv5te/OP_SUB_INT.S */
3941/* File: armv5te/binop.S */
3942    /*
3943     * Generic 32-bit binary operation.  Provide an "instr" line that
3944     * specifies an instruction that performs "result = r0 op r1".
3945     * This could be an ARM instruction or a function call.  (If the result
3946     * comes back in a register other than r0, you can override "result".)
3947     *
3948     * If "chkzero" is set to 1, we perform a divide-by-zero check on
3949     * vCC (r1).  Useful for integer division and modulus.  Note that we
3950     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
3951     * handles it correctly.
3952     *
3953     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
3954     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
3955     *      mul-float, div-float, rem-float
3956     */
3957    /* binop vAA, vBB, vCC */
3958    FETCH(r0, 1)                        @ r0<- CCBB
3959    mov     r9, rINST, lsr #8           @ r9<- AA
3960    mov     r3, r0, lsr #8              @ r3<- CC
3961    and     r2, r0, #255                @ r2<- BB
3962    GET_VREG(r1, r3)                    @ r1<- vCC
3963    GET_VREG(r0, r2)                    @ r0<- vBB
3964    .if 0
3965    cmp     r1, #0                      @ is second operand zero?
3966    beq     common_errDivideByZero
3967    .endif
3968
3969    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3970                               @ optional op; may set condition codes
3971    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
3972    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3973    SET_VREG(r0, r9)               @ vAA<- r0
3974    GOTO_OPCODE(ip)                     @ jump to next instruction
3975    /* 11-14 instructions */
3976
3977
3978
3979/* ------------------------------ */
3980    .balign 64
3981.L_OP_MUL_INT: /* 0x92 */
3982/* File: armv5te/OP_MUL_INT.S */
3983/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
3984/* File: armv5te/binop.S */
3985    /*
3986     * Generic 32-bit binary operation.  Provide an "instr" line that
3987     * specifies an instruction that performs "result = r0 op r1".
3988     * This could be an ARM instruction or a function call.  (If the result
3989     * comes back in a register other than r0, you can override "result".)
3990     *
3991     * If "chkzero" is set to 1, we perform a divide-by-zero check on
3992     * vCC (r1).  Useful for integer division and modulus.  Note that we
3993     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
3994     * handles it correctly.
3995     *
3996     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
3997     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
3998     *      mul-float, div-float, rem-float
3999     */
4000    /* binop vAA, vBB, vCC */
4001    FETCH(r0, 1)                        @ r0<- CCBB
4002    mov     r9, rINST, lsr #8           @ r9<- AA
4003    mov     r3, r0, lsr #8              @ r3<- CC
4004    and     r2, r0, #255                @ r2<- BB
4005    GET_VREG(r1, r3)                    @ r1<- vCC
4006    GET_VREG(r0, r2)                    @ r0<- vBB
4007    .if 0
4008    cmp     r1, #0                      @ is second operand zero?
4009    beq     common_errDivideByZero
4010    .endif
4011
4012    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4013                               @ optional op; may set condition codes
4014    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4015    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4016    SET_VREG(r0, r9)               @ vAA<- r0
4017    GOTO_OPCODE(ip)                     @ jump to next instruction
4018    /* 11-14 instructions */
4019
4020
4021
4022/* ------------------------------ */
4023    .balign 64
4024.L_OP_DIV_INT: /* 0x93 */
4025/* File: armv5te/OP_DIV_INT.S */
4026/* File: armv5te/binop.S */
4027    /*
4028     * Generic 32-bit binary operation.  Provide an "instr" line that
4029     * specifies an instruction that performs "result = r0 op r1".
4030     * This could be an ARM instruction or a function call.  (If the result
4031     * comes back in a register other than r0, you can override "result".)
4032     *
4033     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4034     * vCC (r1).  Useful for integer division and modulus.  Note that we
4035     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4036     * handles it correctly.
4037     *
4038     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4039     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4040     *      mul-float, div-float, rem-float
4041     */
4042    /* binop vAA, vBB, vCC */
4043    FETCH(r0, 1)                        @ r0<- CCBB
4044    mov     r9, rINST, lsr #8           @ r9<- AA
4045    mov     r3, r0, lsr #8              @ r3<- CC
4046    and     r2, r0, #255                @ r2<- BB
4047    GET_VREG(r1, r3)                    @ r1<- vCC
4048    GET_VREG(r0, r2)                    @ r0<- vBB
4049    .if 1
4050    cmp     r1, #0                      @ is second operand zero?
4051    beq     common_errDivideByZero
4052    .endif
4053
4054    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4055                               @ optional op; may set condition codes
4056    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4057    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4058    SET_VREG(r0, r9)               @ vAA<- r0
4059    GOTO_OPCODE(ip)                     @ jump to next instruction
4060    /* 11-14 instructions */
4061
4062
4063
4064/* ------------------------------ */
4065    .balign 64
4066.L_OP_REM_INT: /* 0x94 */
4067/* File: armv5te/OP_REM_INT.S */
4068/* idivmod returns quotient in r0 and remainder in r1 */
4069/* File: armv5te/binop.S */
4070    /*
4071     * Generic 32-bit binary operation.  Provide an "instr" line that
4072     * specifies an instruction that performs "result = r0 op r1".
4073     * This could be an ARM instruction or a function call.  (If the result
4074     * comes back in a register other than r0, you can override "result".)
4075     *
4076     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4077     * vCC (r1).  Useful for integer division and modulus.  Note that we
4078     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4079     * handles it correctly.
4080     *
4081     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4082     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4083     *      mul-float, div-float, rem-float
4084     */
4085    /* binop vAA, vBB, vCC */
4086    FETCH(r0, 1)                        @ r0<- CCBB
4087    mov     r9, rINST, lsr #8           @ r9<- AA
4088    mov     r3, r0, lsr #8              @ r3<- CC
4089    and     r2, r0, #255                @ r2<- BB
4090    GET_VREG(r1, r3)                    @ r1<- vCC
4091    GET_VREG(r0, r2)                    @ r0<- vBB
4092    .if 1
4093    cmp     r1, #0                      @ is second operand zero?
4094    beq     common_errDivideByZero
4095    .endif
4096
4097    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4098                               @ optional op; may set condition codes
4099    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4100    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4101    SET_VREG(r1, r9)               @ vAA<- r1
4102    GOTO_OPCODE(ip)                     @ jump to next instruction
4103    /* 11-14 instructions */
4104
4105
4106
4107/* ------------------------------ */
4108    .balign 64
4109.L_OP_AND_INT: /* 0x95 */
4110/* File: armv5te/OP_AND_INT.S */
4111/* File: armv5te/binop.S */
4112    /*
4113     * Generic 32-bit binary operation.  Provide an "instr" line that
4114     * specifies an instruction that performs "result = r0 op r1".
4115     * This could be an ARM instruction or a function call.  (If the result
4116     * comes back in a register other than r0, you can override "result".)
4117     *
4118     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4119     * vCC (r1).  Useful for integer division and modulus.  Note that we
4120     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4121     * handles it correctly.
4122     *
4123     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4124     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4125     *      mul-float, div-float, rem-float
4126     */
4127    /* binop vAA, vBB, vCC */
4128    FETCH(r0, 1)                        @ r0<- CCBB
4129    mov     r9, rINST, lsr #8           @ r9<- AA
4130    mov     r3, r0, lsr #8              @ r3<- CC
4131    and     r2, r0, #255                @ r2<- BB
4132    GET_VREG(r1, r3)                    @ r1<- vCC
4133    GET_VREG(r0, r2)                    @ r0<- vBB
4134    .if 0
4135    cmp     r1, #0                      @ is second operand zero?
4136    beq     common_errDivideByZero
4137    .endif
4138
4139    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4140                               @ optional op; may set condition codes
4141    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4143    SET_VREG(r0, r9)               @ vAA<- r0
4144    GOTO_OPCODE(ip)                     @ jump to next instruction
4145    /* 11-14 instructions */
4146
4147
4148
4149/* ------------------------------ */
4150    .balign 64
4151.L_OP_OR_INT: /* 0x96 */
4152/* File: armv5te/OP_OR_INT.S */
4153/* File: armv5te/binop.S */
4154    /*
4155     * Generic 32-bit binary operation.  Provide an "instr" line that
4156     * specifies an instruction that performs "result = r0 op r1".
4157     * This could be an ARM instruction or a function call.  (If the result
4158     * comes back in a register other than r0, you can override "result".)
4159     *
4160     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4161     * vCC (r1).  Useful for integer division and modulus.  Note that we
4162     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4163     * handles it correctly.
4164     *
4165     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4166     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4167     *      mul-float, div-float, rem-float
4168     */
4169    /* binop vAA, vBB, vCC */
4170    FETCH(r0, 1)                        @ r0<- CCBB
4171    mov     r9, rINST, lsr #8           @ r9<- AA
4172    mov     r3, r0, lsr #8              @ r3<- CC
4173    and     r2, r0, #255                @ r2<- BB
4174    GET_VREG(r1, r3)                    @ r1<- vCC
4175    GET_VREG(r0, r2)                    @ r0<- vBB
4176    .if 0
4177    cmp     r1, #0                      @ is second operand zero?
4178    beq     common_errDivideByZero
4179    .endif
4180
4181    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4182                               @ optional op; may set condition codes
4183    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4185    SET_VREG(r0, r9)               @ vAA<- r0
4186    GOTO_OPCODE(ip)                     @ jump to next instruction
4187    /* 11-14 instructions */
4188
4189
4190
4191/* ------------------------------ */
4192    .balign 64
4193.L_OP_XOR_INT: /* 0x97 */
4194/* File: armv5te/OP_XOR_INT.S */
4195/* File: armv5te/binop.S */
4196    /*
4197     * Generic 32-bit binary operation.  Provide an "instr" line that
4198     * specifies an instruction that performs "result = r0 op r1".
4199     * This could be an ARM instruction or a function call.  (If the result
4200     * comes back in a register other than r0, you can override "result".)
4201     *
4202     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4203     * vCC (r1).  Useful for integer division and modulus.  Note that we
4204     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4205     * handles it correctly.
4206     *
4207     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4208     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4209     *      mul-float, div-float, rem-float
4210     */
4211    /* binop vAA, vBB, vCC */
4212    FETCH(r0, 1)                        @ r0<- CCBB
4213    mov     r9, rINST, lsr #8           @ r9<- AA
4214    mov     r3, r0, lsr #8              @ r3<- CC
4215    and     r2, r0, #255                @ r2<- BB
4216    GET_VREG(r1, r3)                    @ r1<- vCC
4217    GET_VREG(r0, r2)                    @ r0<- vBB
4218    .if 0
4219    cmp     r1, #0                      @ is second operand zero?
4220    beq     common_errDivideByZero
4221    .endif
4222
4223    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4224                               @ optional op; may set condition codes
4225    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4226    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4227    SET_VREG(r0, r9)               @ vAA<- r0
4228    GOTO_OPCODE(ip)                     @ jump to next instruction
4229    /* 11-14 instructions */
4230
4231
4232
4233/* ------------------------------ */
4234    .balign 64
4235.L_OP_SHL_INT: /* 0x98 */
4236/* File: armv5te/OP_SHL_INT.S */
4237/* File: armv5te/binop.S */
4238    /*
4239     * Generic 32-bit binary operation.  Provide an "instr" line that
4240     * specifies an instruction that performs "result = r0 op r1".
4241     * This could be an ARM instruction or a function call.  (If the result
4242     * comes back in a register other than r0, you can override "result".)
4243     *
4244     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4245     * vCC (r1).  Useful for integer division and modulus.  Note that we
4246     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4247     * handles it correctly.
4248     *
4249     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4250     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4251     *      mul-float, div-float, rem-float
4252     */
4253    /* binop vAA, vBB, vCC */
4254    FETCH(r0, 1)                        @ r0<- CCBB
4255    mov     r9, rINST, lsr #8           @ r9<- AA
4256    mov     r3, r0, lsr #8              @ r3<- CC
4257    and     r2, r0, #255                @ r2<- BB
4258    GET_VREG(r1, r3)                    @ r1<- vCC
4259    GET_VREG(r0, r2)                    @ r0<- vBB
4260    .if 0
4261    cmp     r1, #0                      @ is second operand zero?
4262    beq     common_errDivideByZero
4263    .endif
4264
4265    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4266    and     r1, r1, #31                           @ optional op; may set condition codes
4267    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4269    SET_VREG(r0, r9)               @ vAA<- r0
4270    GOTO_OPCODE(ip)                     @ jump to next instruction
4271    /* 11-14 instructions */
4272
4273
4274
4275/* ------------------------------ */
4276    .balign 64
4277.L_OP_SHR_INT: /* 0x99 */
4278/* File: armv5te/OP_SHR_INT.S */
4279/* File: armv5te/binop.S */
4280    /*
4281     * Generic 32-bit binary operation.  Provide an "instr" line that
4282     * specifies an instruction that performs "result = r0 op r1".
4283     * This could be an ARM instruction or a function call.  (If the result
4284     * comes back in a register other than r0, you can override "result".)
4285     *
4286     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4287     * vCC (r1).  Useful for integer division and modulus.  Note that we
4288     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4289     * handles it correctly.
4290     *
4291     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4292     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4293     *      mul-float, div-float, rem-float
4294     */
4295    /* binop vAA, vBB, vCC */
4296    FETCH(r0, 1)                        @ r0<- CCBB
4297    mov     r9, rINST, lsr #8           @ r9<- AA
4298    mov     r3, r0, lsr #8              @ r3<- CC
4299    and     r2, r0, #255                @ r2<- BB
4300    GET_VREG(r1, r3)                    @ r1<- vCC
4301    GET_VREG(r0, r2)                    @ r0<- vBB
4302    .if 0
4303    cmp     r1, #0                      @ is second operand zero?
4304    beq     common_errDivideByZero
4305    .endif
4306
4307    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4308    and     r1, r1, #31                           @ optional op; may set condition codes
4309    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4310    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4311    SET_VREG(r0, r9)               @ vAA<- r0
4312    GOTO_OPCODE(ip)                     @ jump to next instruction
4313    /* 11-14 instructions */
4314
4315
4316
4317/* ------------------------------ */
4318    .balign 64
4319.L_OP_USHR_INT: /* 0x9a */
4320/* File: armv5te/OP_USHR_INT.S */
4321/* File: armv5te/binop.S */
4322    /*
4323     * Generic 32-bit binary operation.  Provide an "instr" line that
4324     * specifies an instruction that performs "result = r0 op r1".
4325     * This could be an ARM instruction or a function call.  (If the result
4326     * comes back in a register other than r0, you can override "result".)
4327     *
4328     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4329     * vCC (r1).  Useful for integer division and modulus.  Note that we
4330     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4331     * handles it correctly.
4332     *
4333     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4334     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4335     *      mul-float, div-float, rem-float
4336     */
4337    /* binop vAA, vBB, vCC */
4338    FETCH(r0, 1)                        @ r0<- CCBB
4339    mov     r9, rINST, lsr #8           @ r9<- AA
4340    mov     r3, r0, lsr #8              @ r3<- CC
4341    and     r2, r0, #255                @ r2<- BB
4342    GET_VREG(r1, r3)                    @ r1<- vCC
4343    GET_VREG(r0, r2)                    @ r0<- vBB
4344    .if 0
4345    cmp     r1, #0                      @ is second operand zero?
4346    beq     common_errDivideByZero
4347    .endif
4348
4349    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4350    and     r1, r1, #31                           @ optional op; may set condition codes
4351    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4353    SET_VREG(r0, r9)               @ vAA<- r0
4354    GOTO_OPCODE(ip)                     @ jump to next instruction
4355    /* 11-14 instructions */
4356
4357
4358
4359/* ------------------------------ */
4360    .balign 64
4361.L_OP_ADD_LONG: /* 0x9b */
4362/* File: armv5te/OP_ADD_LONG.S */
4363/* File: armv5te/binopWide.S */
4364    /*
4365     * Generic 64-bit binary operation.  Provide an "instr" line that
4366     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4367     * This could be an ARM instruction or a function call.  (If the result
4368     * comes back in a register other than r0, you can override "result".)
4369     *
4370     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4371     * vCC (r1).  Useful for integer division and modulus.
4372     *
4373     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4374     *      xor-long, add-double, sub-double, mul-double, div-double,
4375     *      rem-double
4376     *
4377     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4378     */
4379    /* binop vAA, vBB, vCC */
4380    FETCH(r0, 1)                        @ r0<- CCBB
4381    mov     r9, rINST, lsr #8           @ r9<- AA
4382    and     r2, r0, #255                @ r2<- BB
4383    mov     r3, r0, lsr #8              @ r3<- CC
4384    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4385    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4386    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4387    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4388    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4389    .if 0
4390    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4391    beq     common_errDivideByZero
4392    .endif
4393    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4394
4395    adds    r0, r0, r2                           @ optional op; may set condition codes
4396    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4397    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4398    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4399    GOTO_OPCODE(ip)                     @ jump to next instruction
4400    /* 14-17 instructions */
4401
4402
4403
4404/* ------------------------------ */
4405    .balign 64
4406.L_OP_SUB_LONG: /* 0x9c */
4407/* File: armv5te/OP_SUB_LONG.S */
4408/* File: armv5te/binopWide.S */
4409    /*
4410     * Generic 64-bit binary operation.  Provide an "instr" line that
4411     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4412     * This could be an ARM instruction or a function call.  (If the result
4413     * comes back in a register other than r0, you can override "result".)
4414     *
4415     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4416     * vCC (r1).  Useful for integer division and modulus.
4417     *
4418     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4419     *      xor-long, add-double, sub-double, mul-double, div-double,
4420     *      rem-double
4421     *
4422     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4423     */
4424    /* binop vAA, vBB, vCC */
4425    FETCH(r0, 1)                        @ r0<- CCBB
4426    mov     r9, rINST, lsr #8           @ r9<- AA
4427    and     r2, r0, #255                @ r2<- BB
4428    mov     r3, r0, lsr #8              @ r3<- CC
4429    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4430    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4431    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4432    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4433    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4434    .if 0
4435    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4436    beq     common_errDivideByZero
4437    .endif
4438    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4439
4440    subs    r0, r0, r2                           @ optional op; may set condition codes
4441    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4442    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4443    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4444    GOTO_OPCODE(ip)                     @ jump to next instruction
4445    /* 14-17 instructions */
4446
4447
4448
4449/* ------------------------------ */
4450    .balign 64
4451.L_OP_MUL_LONG: /* 0x9d */
4452/* File: armv5te/OP_MUL_LONG.S */
4453    /*
4454     * Signed 64-bit integer multiply.
4455     *
4456     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4457     *        WX
4458     *      x YZ
4459     *  --------
4460     *     ZW ZX
4461     *  YW YX
4462     *
4463     * The low word of the result holds ZX, the high word holds
4464     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4465     * it doesn't fit in the low 64 bits.
4466     *
4467     * Unlike most ARM math operations, multiply instructions have
4468     * restrictions on using the same register more than once (Rd and Rm
4469     * cannot be the same).
4470     */
4471    /* mul-long vAA, vBB, vCC */
4472    FETCH(r0, 1)                        @ r0<- CCBB
4473    and     r2, r0, #255                @ r2<- BB
4474    mov     r3, r0, lsr #8              @ r3<- CC
4475    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4476    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4477    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4478    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4479    mul     ip, r2, r1                  @  ip<- ZxW
4480    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4481    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4482    mov     r0, rINST, lsr #8           @ r0<- AA
4483    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4484    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4485    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4486    b       .LOP_MUL_LONG_finish
4487
4488/* ------------------------------ */
4489    .balign 64
4490.L_OP_DIV_LONG: /* 0x9e */
4491/* File: armv5te/OP_DIV_LONG.S */
4492/* File: armv5te/binopWide.S */
4493    /*
4494     * Generic 64-bit binary operation.  Provide an "instr" line that
4495     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4496     * This could be an ARM instruction or a function call.  (If the result
4497     * comes back in a register other than r0, you can override "result".)
4498     *
4499     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4500     * vCC (r1).  Useful for integer division and modulus.
4501     *
4502     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4503     *      xor-long, add-double, sub-double, mul-double, div-double,
4504     *      rem-double
4505     *
4506     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4507     */
4508    /* binop vAA, vBB, vCC */
4509    FETCH(r0, 1)                        @ r0<- CCBB
4510    mov     r9, rINST, lsr #8           @ r9<- AA
4511    and     r2, r0, #255                @ r2<- BB
4512    mov     r3, r0, lsr #8              @ r3<- CC
4513    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4514    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4515    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4516    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4517    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4518    .if 1
4519    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4520    beq     common_errDivideByZero
4521    .endif
4522    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4523
4524                               @ optional op; may set condition codes
4525    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4526    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4527    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4528    GOTO_OPCODE(ip)                     @ jump to next instruction
4529    /* 14-17 instructions */
4530
4531
4532
4533/* ------------------------------ */
4534    .balign 64
4535.L_OP_REM_LONG: /* 0x9f */
4536/* File: armv5te/OP_REM_LONG.S */
4537/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4538/* File: armv5te/binopWide.S */
4539    /*
4540     * Generic 64-bit binary operation.  Provide an "instr" line that
4541     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4542     * This could be an ARM instruction or a function call.  (If the result
4543     * comes back in a register other than r0, you can override "result".)
4544     *
4545     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4546     * vCC (r1).  Useful for integer division and modulus.
4547     *
4548     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4549     *      xor-long, add-double, sub-double, mul-double, div-double,
4550     *      rem-double
4551     *
4552     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4553     */
4554    /* binop vAA, vBB, vCC */
4555    FETCH(r0, 1)                        @ r0<- CCBB
4556    mov     r9, rINST, lsr #8           @ r9<- AA
4557    and     r2, r0, #255                @ r2<- BB
4558    mov     r3, r0, lsr #8              @ r3<- CC
4559    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4560    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4561    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4562    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4563    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4564    .if 1
4565    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4566    beq     common_errDivideByZero
4567    .endif
4568    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4569
4570                               @ optional op; may set condition codes
4571    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4572    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4573    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4574    GOTO_OPCODE(ip)                     @ jump to next instruction
4575    /* 14-17 instructions */
4576
4577
4578
4579/* ------------------------------ */
4580    .balign 64
4581.L_OP_AND_LONG: /* 0xa0 */
4582/* File: armv5te/OP_AND_LONG.S */
4583/* File: armv5te/binopWide.S */
4584    /*
4585     * Generic 64-bit binary operation.  Provide an "instr" line that
4586     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4587     * This could be an ARM instruction or a function call.  (If the result
4588     * comes back in a register other than r0, you can override "result".)
4589     *
4590     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4591     * vCC (r1).  Useful for integer division and modulus.
4592     *
4593     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4594     *      xor-long, add-double, sub-double, mul-double, div-double,
4595     *      rem-double
4596     *
4597     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4598     */
4599    /* binop vAA, vBB, vCC */
4600    FETCH(r0, 1)                        @ r0<- CCBB
4601    mov     r9, rINST, lsr #8           @ r9<- AA
4602    and     r2, r0, #255                @ r2<- BB
4603    mov     r3, r0, lsr #8              @ r3<- CC
4604    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4605    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4606    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4607    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4608    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4609    .if 0
4610    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4611    beq     common_errDivideByZero
4612    .endif
4613    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4614
4615    and     r0, r0, r2                           @ optional op; may set condition codes
4616    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4617    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4618    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4619    GOTO_OPCODE(ip)                     @ jump to next instruction
4620    /* 14-17 instructions */
4621
4622
4623
4624/* ------------------------------ */
4625    .balign 64
4626.L_OP_OR_LONG: /* 0xa1 */
4627/* File: armv5te/OP_OR_LONG.S */
4628/* File: armv5te/binopWide.S */
4629    /*
4630     * Generic 64-bit binary operation.  Provide an "instr" line that
4631     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4632     * This could be an ARM instruction or a function call.  (If the result
4633     * comes back in a register other than r0, you can override "result".)
4634     *
4635     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4636     * vCC (r1).  Useful for integer division and modulus.
4637     *
4638     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4639     *      xor-long, add-double, sub-double, mul-double, div-double,
4640     *      rem-double
4641     *
4642     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4643     */
4644    /* binop vAA, vBB, vCC */
4645    FETCH(r0, 1)                        @ r0<- CCBB
4646    mov     r9, rINST, lsr #8           @ r9<- AA
4647    and     r2, r0, #255                @ r2<- BB
4648    mov     r3, r0, lsr #8              @ r3<- CC
4649    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4650    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4651    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4652    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4653    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4654    .if 0
4655    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4656    beq     common_errDivideByZero
4657    .endif
4658    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4659
4660    orr     r0, r0, r2                           @ optional op; may set condition codes
4661    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4662    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4663    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4664    GOTO_OPCODE(ip)                     @ jump to next instruction
4665    /* 14-17 instructions */
4666
4667
4668
4669/* ------------------------------ */
4670    .balign 64
4671.L_OP_XOR_LONG: /* 0xa2 */
4672/* File: armv5te/OP_XOR_LONG.S */
4673/* File: armv5te/binopWide.S */
4674    /*
4675     * Generic 64-bit binary operation.  Provide an "instr" line that
4676     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4677     * This could be an ARM instruction or a function call.  (If the result
4678     * comes back in a register other than r0, you can override "result".)
4679     *
4680     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4681     * vCC (r1).  Useful for integer division and modulus.
4682     *
4683     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4684     *      xor-long, add-double, sub-double, mul-double, div-double,
4685     *      rem-double
4686     *
4687     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4688     */
4689    /* binop vAA, vBB, vCC */
4690    FETCH(r0, 1)                        @ r0<- CCBB
4691    mov     r9, rINST, lsr #8           @ r9<- AA
4692    and     r2, r0, #255                @ r2<- BB
4693    mov     r3, r0, lsr #8              @ r3<- CC
4694    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4695    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4696    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4697    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4698    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4699    .if 0
4700    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4701    beq     common_errDivideByZero
4702    .endif
4703    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4704
4705    eor     r0, r0, r2                           @ optional op; may set condition codes
4706    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4708    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4709    GOTO_OPCODE(ip)                     @ jump to next instruction
4710    /* 14-17 instructions */
4711
4712
4713
4714/* ------------------------------ */
4715    .balign 64
4716.L_OP_SHL_LONG: /* 0xa3 */
4717/* File: armv5te/OP_SHL_LONG.S */
4718    /*
4719     * Long integer shift.  This is different from the generic 32/64-bit
4720     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4721     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4722     * 6 bits of the shift distance.
4723     */
4724    /* shl-long vAA, vBB, vCC */
4725    FETCH(r0, 1)                        @ r0<- CCBB
4726    mov     r9, rINST, lsr #8           @ r9<- AA
4727    and     r3, r0, #255                @ r3<- BB
4728    mov     r0, r0, lsr #8              @ r0<- CC
4729    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4730    GET_VREG(r2, r0)                    @ r2<- vCC
4731    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4732    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4733    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4734
4735    mov     r1, r1, asl r2              @  r1<- r1 << r2
4736    rsb     r3, r2, #32                 @  r3<- 32 - r2
4737    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4738    subs    ip, r2, #32                 @  ip<- r2 - 32
4739    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4740    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4741    b       .LOP_SHL_LONG_finish
4742
4743/* ------------------------------ */
4744    .balign 64
4745.L_OP_SHR_LONG: /* 0xa4 */
4746/* File: armv5te/OP_SHR_LONG.S */
4747    /*
4748     * Long integer shift.  This is different from the generic 32/64-bit
4749     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4750     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4751     * 6 bits of the shift distance.
4752     */
4753    /* shr-long vAA, vBB, vCC */
4754    FETCH(r0, 1)                        @ r0<- CCBB
4755    mov     r9, rINST, lsr #8           @ r9<- AA
4756    and     r3, r0, #255                @ r3<- BB
4757    mov     r0, r0, lsr #8              @ r0<- CC
4758    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4759    GET_VREG(r2, r0)                    @ r2<- vCC
4760    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4761    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4762    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4763
4764    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4765    rsb     r3, r2, #32                 @  r3<- 32 - r2
4766    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4767    subs    ip, r2, #32                 @  ip<- r2 - 32
4768    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4769    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4770    b       .LOP_SHR_LONG_finish
4771
4772/* ------------------------------ */
4773    .balign 64
4774.L_OP_USHR_LONG: /* 0xa5 */
4775/* File: armv5te/OP_USHR_LONG.S */
4776    /*
4777     * Long integer shift.  This is different from the generic 32/64-bit
4778     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4779     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4780     * 6 bits of the shift distance.
4781     */
4782    /* ushr-long vAA, vBB, vCC */
4783    FETCH(r0, 1)                        @ r0<- CCBB
4784    mov     r9, rINST, lsr #8           @ r9<- AA
4785    and     r3, r0, #255                @ r3<- BB
4786    mov     r0, r0, lsr #8              @ r0<- CC
4787    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4788    GET_VREG(r2, r0)                    @ r2<- vCC
4789    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4790    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4791    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4792
4793    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4794    rsb     r3, r2, #32                 @  r3<- 32 - r2
4795    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4796    subs    ip, r2, #32                 @  ip<- r2 - 32
4797    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4798    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4799    b       .LOP_USHR_LONG_finish
4800
4801/* ------------------------------ */
4802    .balign 64
4803.L_OP_ADD_FLOAT: /* 0xa6 */
4804/* File: vfp/OP_ADD_FLOAT.S */
4805/* File: vfp/fbinop.S */
4806    /*
4807     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4808     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4809     * use the "softfp" ABI, this must be an instruction, not a function call.
4810     *
4811     * For: add-float, sub-float, mul-float, div-float
4812     */
4813    /* floatop vAA, vBB, vCC */
4814    FETCH(r0, 1)                        @ r0<- CCBB
4815    mov     r9, rINST, lsr #8           @ r9<- AA
4816    mov     r3, r0, lsr #8              @ r3<- CC
4817    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4818    flds    s1, [r3]                    @ s1<- vCC
4819    and     r2, r0, #255                @ r2<- BB
4820    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4821    flds    s0, [r2]                    @ s0<- vBB
4822
4823    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4824    fadds   s2, s0, s1                              @ s2<- op
4825    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4826    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4827    fsts    s2, [r9]                    @ vAA<- s2
4828    GOTO_OPCODE(ip)                     @ jump to next instruction
4829
4830
4831/* ------------------------------ */
4832    .balign 64
4833.L_OP_SUB_FLOAT: /* 0xa7 */
4834/* File: vfp/OP_SUB_FLOAT.S */
4835/* File: vfp/fbinop.S */
4836    /*
4837     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4838     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4839     * use the "softfp" ABI, this must be an instruction, not a function call.
4840     *
4841     * For: add-float, sub-float, mul-float, div-float
4842     */
4843    /* floatop vAA, vBB, vCC */
4844    FETCH(r0, 1)                        @ r0<- CCBB
4845    mov     r9, rINST, lsr #8           @ r9<- AA
4846    mov     r3, r0, lsr #8              @ r3<- CC
4847    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4848    flds    s1, [r3]                    @ s1<- vCC
4849    and     r2, r0, #255                @ r2<- BB
4850    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4851    flds    s0, [r2]                    @ s0<- vBB
4852
4853    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4854    fsubs   s2, s0, s1                              @ s2<- op
4855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4856    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4857    fsts    s2, [r9]                    @ vAA<- s2
4858    GOTO_OPCODE(ip)                     @ jump to next instruction
4859
4860
4861/* ------------------------------ */
4862    .balign 64
4863.L_OP_MUL_FLOAT: /* 0xa8 */
4864/* File: vfp/OP_MUL_FLOAT.S */
4865/* File: vfp/fbinop.S */
4866    /*
4867     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4868     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4869     * use the "softfp" ABI, this must be an instruction, not a function call.
4870     *
4871     * For: add-float, sub-float, mul-float, div-float
4872     */
4873    /* floatop vAA, vBB, vCC */
4874    FETCH(r0, 1)                        @ r0<- CCBB
4875    mov     r9, rINST, lsr #8           @ r9<- AA
4876    mov     r3, r0, lsr #8              @ r3<- CC
4877    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4878    flds    s1, [r3]                    @ s1<- vCC
4879    and     r2, r0, #255                @ r2<- BB
4880    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4881    flds    s0, [r2]                    @ s0<- vBB
4882
4883    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4884    fmuls   s2, s0, s1                              @ s2<- op
4885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4886    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4887    fsts    s2, [r9]                    @ vAA<- s2
4888    GOTO_OPCODE(ip)                     @ jump to next instruction
4889
4890
4891/* ------------------------------ */
4892    .balign 64
4893.L_OP_DIV_FLOAT: /* 0xa9 */
4894/* File: vfp/OP_DIV_FLOAT.S */
4895/* File: vfp/fbinop.S */
4896    /*
4897     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4898     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4899     * use the "softfp" ABI, this must be an instruction, not a function call.
4900     *
4901     * For: add-float, sub-float, mul-float, div-float
4902     */
4903    /* floatop vAA, vBB, vCC */
4904    FETCH(r0, 1)                        @ r0<- CCBB
4905    mov     r9, rINST, lsr #8           @ r9<- AA
4906    mov     r3, r0, lsr #8              @ r3<- CC
4907    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4908    flds    s1, [r3]                    @ s1<- vCC
4909    and     r2, r0, #255                @ r2<- BB
4910    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4911    flds    s0, [r2]                    @ s0<- vBB
4912
4913    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4914    fdivs   s2, s0, s1                              @ s2<- op
4915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4916    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4917    fsts    s2, [r9]                    @ vAA<- s2
4918    GOTO_OPCODE(ip)                     @ jump to next instruction
4919
4920
4921/* ------------------------------ */
4922    .balign 64
4923.L_OP_REM_FLOAT: /* 0xaa */
4924/* File: armv5te/OP_REM_FLOAT.S */
4925/* EABI doesn't define a float remainder function, but libm does */
4926/* File: armv5te/binop.S */
4927    /*
4928     * Generic 32-bit binary operation.  Provide an "instr" line that
4929     * specifies an instruction that performs "result = r0 op r1".
4930     * This could be an ARM instruction or a function call.  (If the result
4931     * comes back in a register other than r0, you can override "result".)
4932     *
4933     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4934     * vCC (r1).  Useful for integer division and modulus.  Note that we
4935     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4936     * handles it correctly.
4937     *
4938     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4939     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4940     *      mul-float, div-float, rem-float
4941     */
4942    /* binop vAA, vBB, vCC */
4943    FETCH(r0, 1)                        @ r0<- CCBB
4944    mov     r9, rINST, lsr #8           @ r9<- AA
4945    mov     r3, r0, lsr #8              @ r3<- CC
4946    and     r2, r0, #255                @ r2<- BB
4947    GET_VREG(r1, r3)                    @ r1<- vCC
4948    GET_VREG(r0, r2)                    @ r0<- vBB
4949    .if 0
4950    cmp     r1, #0                      @ is second operand zero?
4951    beq     common_errDivideByZero
4952    .endif
4953
4954    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4955                               @ optional op; may set condition codes
4956    bl      fmodf                              @ r0<- op, r0-r3 changed
4957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4958    SET_VREG(r0, r9)               @ vAA<- r0
4959    GOTO_OPCODE(ip)                     @ jump to next instruction
4960    /* 11-14 instructions */
4961
4962
4963
4964/* ------------------------------ */
4965    .balign 64
4966.L_OP_ADD_DOUBLE: /* 0xab */
4967/* File: vfp/OP_ADD_DOUBLE.S */
4968/* File: vfp/fbinopWide.S */
4969    /*
4970     * Generic 64-bit double-precision floating point binary operation.
4971     * Provide an "instr" line that specifies an instruction that performs
4972     * "d2 = d0 op d1".
4973     *
4974     * for: add-double, sub-double, mul-double, div-double
4975     */
4976    /* doubleop vAA, vBB, vCC */
4977    FETCH(r0, 1)                        @ r0<- CCBB
4978    mov     r9, rINST, lsr #8           @ r9<- AA
4979    mov     r3, r0, lsr #8              @ r3<- CC
4980    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4981    fldd    d1, [r3]                    @ d1<- vCC
4982    and     r2, r0, #255                @ r2<- BB
4983    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4984    fldd    d0, [r2]                    @ d0<- vBB
4985
4986    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4987    faddd   d2, d0, d1                              @ s2<- op
4988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4989    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4990    fstd    d2, [r9]                    @ vAA<- d2
4991    GOTO_OPCODE(ip)                     @ jump to next instruction
4992
4993
4994/* ------------------------------ */
4995    .balign 64
4996.L_OP_SUB_DOUBLE: /* 0xac */
4997/* File: vfp/OP_SUB_DOUBLE.S */
4998/* File: vfp/fbinopWide.S */
4999    /*
5000     * Generic 64-bit double-precision floating point binary operation.
5001     * Provide an "instr" line that specifies an instruction that performs
5002     * "d2 = d0 op d1".
5003     *
5004     * for: add-double, sub-double, mul-double, div-double
5005     */
5006    /* doubleop vAA, vBB, vCC */
5007    FETCH(r0, 1)                        @ r0<- CCBB
5008    mov     r9, rINST, lsr #8           @ r9<- AA
5009    mov     r3, r0, lsr #8              @ r3<- CC
5010    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5011    fldd    d1, [r3]                    @ d1<- vCC
5012    and     r2, r0, #255                @ r2<- BB
5013    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5014    fldd    d0, [r2]                    @ d0<- vBB
5015
5016    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5017    fsubd   d2, d0, d1                              @ s2<- op
5018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5019    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5020    fstd    d2, [r9]                    @ vAA<- d2
5021    GOTO_OPCODE(ip)                     @ jump to next instruction
5022
5023
5024/* ------------------------------ */
5025    .balign 64
5026.L_OP_MUL_DOUBLE: /* 0xad */
5027/* File: vfp/OP_MUL_DOUBLE.S */
5028/* File: vfp/fbinopWide.S */
5029    /*
5030     * Generic 64-bit double-precision floating point binary operation.
5031     * Provide an "instr" line that specifies an instruction that performs
5032     * "d2 = d0 op d1".
5033     *
5034     * for: add-double, sub-double, mul-double, div-double
5035     */
5036    /* doubleop vAA, vBB, vCC */
5037    FETCH(r0, 1)                        @ r0<- CCBB
5038    mov     r9, rINST, lsr #8           @ r9<- AA
5039    mov     r3, r0, lsr #8              @ r3<- CC
5040    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5041    fldd    d1, [r3]                    @ d1<- vCC
5042    and     r2, r0, #255                @ r2<- BB
5043    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5044    fldd    d0, [r2]                    @ d0<- vBB
5045
5046    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5047    fmuld   d2, d0, d1                              @ s2<- op
5048    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5049    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5050    fstd    d2, [r9]                    @ vAA<- d2
5051    GOTO_OPCODE(ip)                     @ jump to next instruction
5052
5053
5054/* ------------------------------ */
5055    .balign 64
5056.L_OP_DIV_DOUBLE: /* 0xae */
5057/* File: vfp/OP_DIV_DOUBLE.S */
5058/* File: vfp/fbinopWide.S */
5059    /*
5060     * Generic 64-bit double-precision floating point binary operation.
5061     * Provide an "instr" line that specifies an instruction that performs
5062     * "d2 = d0 op d1".
5063     *
5064     * for: add-double, sub-double, mul-double, div-double
5065     */
5066    /* doubleop vAA, vBB, vCC */
5067    FETCH(r0, 1)                        @ r0<- CCBB
5068    mov     r9, rINST, lsr #8           @ r9<- AA
5069    mov     r3, r0, lsr #8              @ r3<- CC
5070    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5071    fldd    d1, [r3]                    @ d1<- vCC
5072    and     r2, r0, #255                @ r2<- BB
5073    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5074    fldd    d0, [r2]                    @ d0<- vBB
5075
5076    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5077    fdivd   d2, d0, d1                              @ s2<- op
5078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5079    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5080    fstd    d2, [r9]                    @ vAA<- d2
5081    GOTO_OPCODE(ip)                     @ jump to next instruction
5082
5083
5084/* ------------------------------ */
5085    .balign 64
5086.L_OP_REM_DOUBLE: /* 0xaf */
5087/* File: armv5te/OP_REM_DOUBLE.S */
5088/* EABI doesn't define a double remainder function, but libm does */
5089/* File: armv5te/binopWide.S */
5090    /*
5091     * Generic 64-bit binary operation.  Provide an "instr" line that
5092     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5093     * This could be an ARM instruction or a function call.  (If the result
5094     * comes back in a register other than r0, you can override "result".)
5095     *
5096     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5097     * vCC (r1).  Useful for integer division and modulus.
5098     *
5099     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5100     *      xor-long, add-double, sub-double, mul-double, div-double,
5101     *      rem-double
5102     *
5103     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5104     */
5105    /* binop vAA, vBB, vCC */
5106    FETCH(r0, 1)                        @ r0<- CCBB
5107    mov     r9, rINST, lsr #8           @ r9<- AA
5108    and     r2, r0, #255                @ r2<- BB
5109    mov     r3, r0, lsr #8              @ r3<- CC
5110    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5111    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5112    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5113    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5114    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5115    .if 0
5116    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5117    beq     common_errDivideByZero
5118    .endif
5119    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5120
5121                               @ optional op; may set condition codes
5122    bl      fmod                              @ result<- op, r0-r3 changed
5123    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5124    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5125    GOTO_OPCODE(ip)                     @ jump to next instruction
5126    /* 14-17 instructions */
5127
5128
5129
5130/* ------------------------------ */
5131    .balign 64
5132.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5133/* File: armv5te/OP_ADD_INT_2ADDR.S */
5134/* File: armv5te/binop2addr.S */
5135    /*
5136     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5137     * that specifies an instruction that performs "result = r0 op r1".
5138     * This could be an ARM instruction or a function call.  (If the result
5139     * comes back in a register other than r0, you can override "result".)
5140     *
5141     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5142     * vCC (r1).  Useful for integer division and modulus.
5143     *
5144     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5145     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5146     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5147     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5148     */
5149    /* binop/2addr vA, vB */
5150    mov     r9, rINST, lsr #8           @ r9<- A+
5151    mov     r3, rINST, lsr #12          @ r3<- B
5152    and     r9, r9, #15
5153    GET_VREG(r0, r9)                    @ r0<- vA
5154    GET_VREG(r1, r3)                    @ r1<- vB
5155    .if 0
5156    cmp     r1, #0                      @ is second operand zero?
5157    beq     common_errDivideByZero
5158    .endif
5159    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5160
5161                               @ optional op; may set condition codes
5162    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5163    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5164    SET_VREG(r0, r9)               @ vAA<- r0
5165    GOTO_OPCODE(ip)                     @ jump to next instruction
5166    /* 10-13 instructions */
5167
5168
5169
5170/* ------------------------------ */
5171    .balign 64
5172.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5173/* File: armv5te/OP_SUB_INT_2ADDR.S */
5174/* File: armv5te/binop2addr.S */
5175    /*
5176     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5177     * that specifies an instruction that performs "result = r0 op r1".
5178     * This could be an ARM instruction or a function call.  (If the result
5179     * comes back in a register other than r0, you can override "result".)
5180     *
5181     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5182     * vCC (r1).  Useful for integer division and modulus.
5183     *
5184     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5185     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5186     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5187     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5188     */
5189    /* binop/2addr vA, vB */
5190    mov     r9, rINST, lsr #8           @ r9<- A+
5191    mov     r3, rINST, lsr #12          @ r3<- B
5192    and     r9, r9, #15
5193    GET_VREG(r0, r9)                    @ r0<- vA
5194    GET_VREG(r1, r3)                    @ r1<- vB
5195    .if 0
5196    cmp     r1, #0                      @ is second operand zero?
5197    beq     common_errDivideByZero
5198    .endif
5199    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5200
5201                               @ optional op; may set condition codes
5202    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5204    SET_VREG(r0, r9)               @ vAA<- r0
5205    GOTO_OPCODE(ip)                     @ jump to next instruction
5206    /* 10-13 instructions */
5207
5208
5209
5210/* ------------------------------ */
5211    .balign 64
5212.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5213/* File: armv5te/OP_MUL_INT_2ADDR.S */
5214/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5215/* File: armv5te/binop2addr.S */
5216    /*
5217     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5218     * that specifies an instruction that performs "result = r0 op r1".
5219     * This could be an ARM instruction or a function call.  (If the result
5220     * comes back in a register other than r0, you can override "result".)
5221     *
5222     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5223     * vCC (r1).  Useful for integer division and modulus.
5224     *
5225     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5226     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5227     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5228     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5229     */
5230    /* binop/2addr vA, vB */
5231    mov     r9, rINST, lsr #8           @ r9<- A+
5232    mov     r3, rINST, lsr #12          @ r3<- B
5233    and     r9, r9, #15
5234    GET_VREG(r0, r9)                    @ r0<- vA
5235    GET_VREG(r1, r3)                    @ r1<- vB
5236    .if 0
5237    cmp     r1, #0                      @ is second operand zero?
5238    beq     common_errDivideByZero
5239    .endif
5240    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5241
5242                               @ optional op; may set condition codes
5243    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5244    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5245    SET_VREG(r0, r9)               @ vAA<- r0
5246    GOTO_OPCODE(ip)                     @ jump to next instruction
5247    /* 10-13 instructions */
5248
5249
5250
5251/* ------------------------------ */
5252    .balign 64
5253.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5254/* File: armv5te/OP_DIV_INT_2ADDR.S */
5255/* File: armv5te/binop2addr.S */
5256    /*
5257     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5258     * that specifies an instruction that performs "result = r0 op r1".
5259     * This could be an ARM instruction or a function call.  (If the result
5260     * comes back in a register other than r0, you can override "result".)
5261     *
5262     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5263     * vCC (r1).  Useful for integer division and modulus.
5264     *
5265     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5266     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5267     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5268     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5269     */
5270    /* binop/2addr vA, vB */
5271    mov     r9, rINST, lsr #8           @ r9<- A+
5272    mov     r3, rINST, lsr #12          @ r3<- B
5273    and     r9, r9, #15
5274    GET_VREG(r0, r9)                    @ r0<- vA
5275    GET_VREG(r1, r3)                    @ r1<- vB
5276    .if 1
5277    cmp     r1, #0                      @ is second operand zero?
5278    beq     common_errDivideByZero
5279    .endif
5280    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5281
5282                               @ optional op; may set condition codes
5283    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5285    SET_VREG(r0, r9)               @ vAA<- r0
5286    GOTO_OPCODE(ip)                     @ jump to next instruction
5287    /* 10-13 instructions */
5288
5289
5290
5291/* ------------------------------ */
5292    .balign 64
5293.L_OP_REM_INT_2ADDR: /* 0xb4 */
5294/* File: armv5te/OP_REM_INT_2ADDR.S */
5295/* idivmod returns quotient in r0 and remainder in r1 */
5296/* File: armv5te/binop2addr.S */
5297    /*
5298     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5299     * that specifies an instruction that performs "result = r0 op r1".
5300     * This could be an ARM instruction or a function call.  (If the result
5301     * comes back in a register other than r0, you can override "result".)
5302     *
5303     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5304     * vCC (r1).  Useful for integer division and modulus.
5305     *
5306     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5307     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5308     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5309     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5310     */
5311    /* binop/2addr vA, vB */
5312    mov     r9, rINST, lsr #8           @ r9<- A+
5313    mov     r3, rINST, lsr #12          @ r3<- B
5314    and     r9, r9, #15
5315    GET_VREG(r0, r9)                    @ r0<- vA
5316    GET_VREG(r1, r3)                    @ r1<- vB
5317    .if 1
5318    cmp     r1, #0                      @ is second operand zero?
5319    beq     common_errDivideByZero
5320    .endif
5321    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5322
5323                               @ optional op; may set condition codes
5324    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5326    SET_VREG(r1, r9)               @ vAA<- r1
5327    GOTO_OPCODE(ip)                     @ jump to next instruction
5328    /* 10-13 instructions */
5329
5330
5331
5332/* ------------------------------ */
5333    .balign 64
5334.L_OP_AND_INT_2ADDR: /* 0xb5 */
5335/* File: armv5te/OP_AND_INT_2ADDR.S */
5336/* File: armv5te/binop2addr.S */
5337    /*
5338     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5339     * that specifies an instruction that performs "result = r0 op r1".
5340     * This could be an ARM instruction or a function call.  (If the result
5341     * comes back in a register other than r0, you can override "result".)
5342     *
5343     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5344     * vCC (r1).  Useful for integer division and modulus.
5345     *
5346     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5347     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5348     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5349     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5350     */
5351    /* binop/2addr vA, vB */
5352    mov     r9, rINST, lsr #8           @ r9<- A+
5353    mov     r3, rINST, lsr #12          @ r3<- B
5354    and     r9, r9, #15
5355    GET_VREG(r0, r9)                    @ r0<- vA
5356    GET_VREG(r1, r3)                    @ r1<- vB
5357    .if 0
5358    cmp     r1, #0                      @ is second operand zero?
5359    beq     common_errDivideByZero
5360    .endif
5361    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5362
5363                               @ optional op; may set condition codes
5364    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5365    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5366    SET_VREG(r0, r9)               @ vAA<- r0
5367    GOTO_OPCODE(ip)                     @ jump to next instruction
5368    /* 10-13 instructions */
5369
5370
5371
5372/* ------------------------------ */
5373    .balign 64
5374.L_OP_OR_INT_2ADDR: /* 0xb6 */
5375/* File: armv5te/OP_OR_INT_2ADDR.S */
5376/* File: armv5te/binop2addr.S */
5377    /*
5378     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5379     * that specifies an instruction that performs "result = r0 op r1".
5380     * This could be an ARM instruction or a function call.  (If the result
5381     * comes back in a register other than r0, you can override "result".)
5382     *
5383     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5384     * vCC (r1).  Useful for integer division and modulus.
5385     *
5386     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5387     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5388     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5389     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5390     */
5391    /* binop/2addr vA, vB */
5392    mov     r9, rINST, lsr #8           @ r9<- A+
5393    mov     r3, rINST, lsr #12          @ r3<- B
5394    and     r9, r9, #15
5395    GET_VREG(r0, r9)                    @ r0<- vA
5396    GET_VREG(r1, r3)                    @ r1<- vB
5397    .if 0
5398    cmp     r1, #0                      @ is second operand zero?
5399    beq     common_errDivideByZero
5400    .endif
5401    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5402
5403                               @ optional op; may set condition codes
5404    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5406    SET_VREG(r0, r9)               @ vAA<- r0
5407    GOTO_OPCODE(ip)                     @ jump to next instruction
5408    /* 10-13 instructions */
5409
5410
5411
5412/* ------------------------------ */
5413    .balign 64
5414.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5415/* File: armv5te/OP_XOR_INT_2ADDR.S */
5416/* File: armv5te/binop2addr.S */
5417    /*
5418     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5419     * that specifies an instruction that performs "result = r0 op r1".
5420     * This could be an ARM instruction or a function call.  (If the result
5421     * comes back in a register other than r0, you can override "result".)
5422     *
5423     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5424     * vCC (r1).  Useful for integer division and modulus.
5425     *
5426     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5427     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5428     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5429     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5430     */
5431    /* binop/2addr vA, vB */
5432    mov     r9, rINST, lsr #8           @ r9<- A+
5433    mov     r3, rINST, lsr #12          @ r3<- B
5434    and     r9, r9, #15
5435    GET_VREG(r0, r9)                    @ r0<- vA
5436    GET_VREG(r1, r3)                    @ r1<- vB
5437    .if 0
5438    cmp     r1, #0                      @ is second operand zero?
5439    beq     common_errDivideByZero
5440    .endif
5441    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5442
5443                               @ optional op; may set condition codes
5444    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5445    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5446    SET_VREG(r0, r9)               @ vAA<- r0
5447    GOTO_OPCODE(ip)                     @ jump to next instruction
5448    /* 10-13 instructions */
5449
5450
5451
5452/* ------------------------------ */
5453    .balign 64
5454.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5455/* File: armv5te/OP_SHL_INT_2ADDR.S */
5456/* File: armv5te/binop2addr.S */
5457    /*
5458     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5459     * that specifies an instruction that performs "result = r0 op r1".
5460     * This could be an ARM instruction or a function call.  (If the result
5461     * comes back in a register other than r0, you can override "result".)
5462     *
5463     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5464     * vCC (r1).  Useful for integer division and modulus.
5465     *
5466     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5467     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5468     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5469     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5470     */
5471    /* binop/2addr vA, vB */
5472    mov     r9, rINST, lsr #8           @ r9<- A+
5473    mov     r3, rINST, lsr #12          @ r3<- B
5474    and     r9, r9, #15
5475    GET_VREG(r0, r9)                    @ r0<- vA
5476    GET_VREG(r1, r3)                    @ r1<- vB
5477    .if 0
5478    cmp     r1, #0                      @ is second operand zero?
5479    beq     common_errDivideByZero
5480    .endif
5481    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5482
5483    and     r1, r1, #31                           @ optional op; may set condition codes
5484    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5486    SET_VREG(r0, r9)               @ vAA<- r0
5487    GOTO_OPCODE(ip)                     @ jump to next instruction
5488    /* 10-13 instructions */
5489
5490
5491
5492/* ------------------------------ */
5493    .balign 64
5494.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5495/* File: armv5te/OP_SHR_INT_2ADDR.S */
5496/* File: armv5te/binop2addr.S */
5497    /*
5498     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5499     * that specifies an instruction that performs "result = r0 op r1".
5500     * This could be an ARM instruction or a function call.  (If the result
5501     * comes back in a register other than r0, you can override "result".)
5502     *
5503     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5504     * vCC (r1).  Useful for integer division and modulus.
5505     *
5506     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5507     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5508     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5509     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5510     */
5511    /* binop/2addr vA, vB */
5512    mov     r9, rINST, lsr #8           @ r9<- A+
5513    mov     r3, rINST, lsr #12          @ r3<- B
5514    and     r9, r9, #15
5515    GET_VREG(r0, r9)                    @ r0<- vA
5516    GET_VREG(r1, r3)                    @ r1<- vB
5517    .if 0
5518    cmp     r1, #0                      @ is second operand zero?
5519    beq     common_errDivideByZero
5520    .endif
5521    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5522
5523    and     r1, r1, #31                           @ optional op; may set condition codes
5524    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5525    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5526    SET_VREG(r0, r9)               @ vAA<- r0
5527    GOTO_OPCODE(ip)                     @ jump to next instruction
5528    /* 10-13 instructions */
5529
5530
5531
5532/* ------------------------------ */
5533    .balign 64
5534.L_OP_USHR_INT_2ADDR: /* 0xba */
5535/* File: armv5te/OP_USHR_INT_2ADDR.S */
5536/* File: armv5te/binop2addr.S */
5537    /*
5538     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5539     * that specifies an instruction that performs "result = r0 op r1".
5540     * This could be an ARM instruction or a function call.  (If the result
5541     * comes back in a register other than r0, you can override "result".)
5542     *
5543     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5544     * vCC (r1).  Useful for integer division and modulus.
5545     *
5546     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5547     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5548     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5549     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5550     */
5551    /* binop/2addr vA, vB */
5552    mov     r9, rINST, lsr #8           @ r9<- A+
5553    mov     r3, rINST, lsr #12          @ r3<- B
5554    and     r9, r9, #15
5555    GET_VREG(r0, r9)                    @ r0<- vA
5556    GET_VREG(r1, r3)                    @ r1<- vB
5557    .if 0
5558    cmp     r1, #0                      @ is second operand zero?
5559    beq     common_errDivideByZero
5560    .endif
5561    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5562
5563    and     r1, r1, #31                           @ optional op; may set condition codes
5564    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5565    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5566    SET_VREG(r0, r9)               @ vAA<- r0
5567    GOTO_OPCODE(ip)                     @ jump to next instruction
5568    /* 10-13 instructions */
5569
5570
5571
5572/* ------------------------------ */
5573    .balign 64
5574.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5575/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5576/* File: armv5te/binopWide2addr.S */
5577    /*
5578     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5579     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5580     * This could be an ARM instruction or a function call.  (If the result
5581     * comes back in a register other than r0, you can override "result".)
5582     *
5583     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5584     * vCC (r1).  Useful for integer division and modulus.
5585     *
5586     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5587     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5588     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5589     *      rem-double/2addr
5590     */
5591    /* binop/2addr vA, vB */
5592    mov     r9, rINST, lsr #8           @ r9<- A+
5593    mov     r1, rINST, lsr #12          @ r1<- B
5594    and     r9, r9, #15
5595    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5596    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5597    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5598    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5599    .if 0
5600    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5601    beq     common_errDivideByZero
5602    .endif
5603    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5604
5605    adds    r0, r0, r2                           @ optional op; may set condition codes
5606    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5608    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5609    GOTO_OPCODE(ip)                     @ jump to next instruction
5610    /* 12-15 instructions */
5611
5612
5613
5614/* ------------------------------ */
5615    .balign 64
5616.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5617/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5618/* File: armv5te/binopWide2addr.S */
5619    /*
5620     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5621     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5622     * This could be an ARM instruction or a function call.  (If the result
5623     * comes back in a register other than r0, you can override "result".)
5624     *
5625     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5626     * vCC (r1).  Useful for integer division and modulus.
5627     *
5628     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5629     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5630     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5631     *      rem-double/2addr
5632     */
5633    /* binop/2addr vA, vB */
5634    mov     r9, rINST, lsr #8           @ r9<- A+
5635    mov     r1, rINST, lsr #12          @ r1<- B
5636    and     r9, r9, #15
5637    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5638    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5639    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5640    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5641    .if 0
5642    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5643    beq     common_errDivideByZero
5644    .endif
5645    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5646
5647    subs    r0, r0, r2                           @ optional op; may set condition codes
5648    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5650    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5651    GOTO_OPCODE(ip)                     @ jump to next instruction
5652    /* 12-15 instructions */
5653
5654
5655
5656/* ------------------------------ */
5657    .balign 64
5658.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5659/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5660    /*
5661     * Signed 64-bit integer multiply, "/2addr" version.
5662     *
5663     * See OP_MUL_LONG for an explanation.
5664     *
5665     * We get a little tight on registers, so to avoid looking up &fp[A]
5666     * again we stuff it into rINST.
5667     */
5668    /* mul-long/2addr vA, vB */
5669    mov     r9, rINST, lsr #8           @ r9<- A+
5670    mov     r1, rINST, lsr #12          @ r1<- B
5671    and     r9, r9, #15
5672    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5673    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5674    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5675    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5676    mul     ip, r2, r1                  @  ip<- ZxW
5677    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5678    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5679    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5680    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5681    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5682    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5683    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5684    GOTO_OPCODE(ip)                     @ jump to next instruction
5685
5686
5687/* ------------------------------ */
5688    .balign 64
5689.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5690/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5691/* File: armv5te/binopWide2addr.S */
5692    /*
5693     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5694     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5695     * This could be an ARM instruction or a function call.  (If the result
5696     * comes back in a register other than r0, you can override "result".)
5697     *
5698     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5699     * vCC (r1).  Useful for integer division and modulus.
5700     *
5701     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5702     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5703     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5704     *      rem-double/2addr
5705     */
5706    /* binop/2addr vA, vB */
5707    mov     r9, rINST, lsr #8           @ r9<- A+
5708    mov     r1, rINST, lsr #12          @ r1<- B
5709    and     r9, r9, #15
5710    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5711    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5712    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5713    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5714    .if 1
5715    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5716    beq     common_errDivideByZero
5717    .endif
5718    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5719
5720                               @ optional op; may set condition codes
5721    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5722    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5723    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5724    GOTO_OPCODE(ip)                     @ jump to next instruction
5725    /* 12-15 instructions */
5726
5727
5728
5729/* ------------------------------ */
5730    .balign 64
5731.L_OP_REM_LONG_2ADDR: /* 0xbf */
5732/* File: armv5te/OP_REM_LONG_2ADDR.S */
5733/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5734/* File: armv5te/binopWide2addr.S */
5735    /*
5736     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5737     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5738     * This could be an ARM instruction or a function call.  (If the result
5739     * comes back in a register other than r0, you can override "result".)
5740     *
5741     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5742     * vCC (r1).  Useful for integer division and modulus.
5743     *
5744     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5745     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5746     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5747     *      rem-double/2addr
5748     */
5749    /* binop/2addr vA, vB */
5750    mov     r9, rINST, lsr #8           @ r9<- A+
5751    mov     r1, rINST, lsr #12          @ r1<- B
5752    and     r9, r9, #15
5753    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5754    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5755    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5756    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5757    .if 1
5758    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5759    beq     common_errDivideByZero
5760    .endif
5761    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5762
5763                               @ optional op; may set condition codes
5764    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5765    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5766    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5767    GOTO_OPCODE(ip)                     @ jump to next instruction
5768    /* 12-15 instructions */
5769
5770
5771
5772/* ------------------------------ */
5773    .balign 64
5774.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5775/* File: armv5te/OP_AND_LONG_2ADDR.S */
5776/* File: armv5te/binopWide2addr.S */
5777    /*
5778     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5779     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5780     * This could be an ARM instruction or a function call.  (If the result
5781     * comes back in a register other than r0, you can override "result".)
5782     *
5783     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5784     * vCC (r1).  Useful for integer division and modulus.
5785     *
5786     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5787     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5788     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5789     *      rem-double/2addr
5790     */
5791    /* binop/2addr vA, vB */
5792    mov     r9, rINST, lsr #8           @ r9<- A+
5793    mov     r1, rINST, lsr #12          @ r1<- B
5794    and     r9, r9, #15
5795    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5796    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5797    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5798    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5799    .if 0
5800    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5801    beq     common_errDivideByZero
5802    .endif
5803    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5804
5805    and     r0, r0, r2                           @ optional op; may set condition codes
5806    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5808    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5809    GOTO_OPCODE(ip)                     @ jump to next instruction
5810    /* 12-15 instructions */
5811
5812
5813
5814/* ------------------------------ */
5815    .balign 64
5816.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5817/* File: armv5te/OP_OR_LONG_2ADDR.S */
5818/* File: armv5te/binopWide2addr.S */
5819    /*
5820     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5821     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5822     * This could be an ARM instruction or a function call.  (If the result
5823     * comes back in a register other than r0, you can override "result".)
5824     *
5825     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5826     * vCC (r1).  Useful for integer division and modulus.
5827     *
5828     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5829     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5830     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5831     *      rem-double/2addr
5832     */
5833    /* binop/2addr vA, vB */
5834    mov     r9, rINST, lsr #8           @ r9<- A+
5835    mov     r1, rINST, lsr #12          @ r1<- B
5836    and     r9, r9, #15
5837    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5838    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5839    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5840    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5841    .if 0
5842    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5843    beq     common_errDivideByZero
5844    .endif
5845    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5846
5847    orr     r0, r0, r2                           @ optional op; may set condition codes
5848    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5849    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5850    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5851    GOTO_OPCODE(ip)                     @ jump to next instruction
5852    /* 12-15 instructions */
5853
5854
5855
5856/* ------------------------------ */
5857    .balign 64
5858.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5859/* File: armv5te/OP_XOR_LONG_2ADDR.S */
5860/* File: armv5te/binopWide2addr.S */
5861    /*
5862     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5863     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5864     * This could be an ARM instruction or a function call.  (If the result
5865     * comes back in a register other than r0, you can override "result".)
5866     *
5867     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5868     * vCC (r1).  Useful for integer division and modulus.
5869     *
5870     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5871     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5872     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5873     *      rem-double/2addr
5874     */
5875    /* binop/2addr vA, vB */
5876    mov     r9, rINST, lsr #8           @ r9<- A+
5877    mov     r1, rINST, lsr #12          @ r1<- B
5878    and     r9, r9, #15
5879    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5880    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5881    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5882    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5883    .if 0
5884    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5885    beq     common_errDivideByZero
5886    .endif
5887    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5888
5889    eor     r0, r0, r2                           @ optional op; may set condition codes
5890    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5891    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5892    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5893    GOTO_OPCODE(ip)                     @ jump to next instruction
5894    /* 12-15 instructions */
5895
5896
5897
5898/* ------------------------------ */
5899    .balign 64
5900.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5901/* File: armv5te/OP_SHL_LONG_2ADDR.S */
5902    /*
5903     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5904     * 32-bit shift distance.
5905     */
5906    /* shl-long/2addr vA, vB */
5907    mov     r9, rINST, lsr #8           @ r9<- A+
5908    mov     r3, rINST, lsr #12          @ r3<- B
5909    and     r9, r9, #15
5910    GET_VREG(r2, r3)                    @ r2<- vB
5911    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5912    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5913    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5914
5915    mov     r1, r1, asl r2              @  r1<- r1 << r2
5916    rsb     r3, r2, #32                 @  r3<- 32 - r2
5917    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5918    subs    ip, r2, #32                 @  ip<- r2 - 32
5919    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5920    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5921    mov     r0, r0, asl r2              @  r0<- r0 << r2
5922    b       .LOP_SHL_LONG_2ADDR_finish
5923
5924/* ------------------------------ */
5925    .balign 64
5926.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
5927/* File: armv5te/OP_SHR_LONG_2ADDR.S */
5928    /*
5929     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5930     * 32-bit shift distance.
5931     */
5932    /* shr-long/2addr vA, vB */
5933    mov     r9, rINST, lsr #8           @ r9<- A+
5934    mov     r3, rINST, lsr #12          @ r3<- B
5935    and     r9, r9, #15
5936    GET_VREG(r2, r3)                    @ r2<- vB
5937    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5938    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5939    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5940
5941    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5942    rsb     r3, r2, #32                 @  r3<- 32 - r2
5943    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5944    subs    ip, r2, #32                 @  ip<- r2 - 32
5945    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5946    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
5947    mov     r1, r1, asr r2              @  r1<- r1 >> r2
5948    b       .LOP_SHR_LONG_2ADDR_finish
5949
5950/* ------------------------------ */
5951    .balign 64
5952.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
5953/* File: armv5te/OP_USHR_LONG_2ADDR.S */
5954    /*
5955     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5956     * 32-bit shift distance.
5957     */
5958    /* ushr-long/2addr vA, vB */
5959    mov     r9, rINST, lsr #8           @ r9<- A+
5960    mov     r3, rINST, lsr #12          @ r3<- B
5961    and     r9, r9, #15
5962    GET_VREG(r2, r3)                    @ r2<- vB
5963    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5964    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5965    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5966
5967    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5968    rsb     r3, r2, #32                 @  r3<- 32 - r2
5969    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5970    subs    ip, r2, #32                 @  ip<- r2 - 32
5971    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5972    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5973    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
5974    b       .LOP_USHR_LONG_2ADDR_finish
5975
5976/* ------------------------------ */
5977    .balign 64
5978.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
5979/* File: vfp/OP_ADD_FLOAT_2ADDR.S */
5980/* File: vfp/fbinop2addr.S */
5981    /*
5982     * Generic 32-bit floating point "/2addr" binary operation.  Provide
5983     * an "instr" line that specifies an instruction that performs
5984     * "s2 = s0 op s1".
5985     *
5986     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
5987     */
5988    /* binop/2addr vA, vB */
5989    mov     r3, rINST, lsr #12          @ r3<- B
5990    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
5991    flds    s1, [r3]                    @ s1<- vB
5992    mov     r9, rINST, lsr #8           @ r9<- A+
5993    and     r9, r9, #15                 @ r9<- A
5994    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
5995    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5996    flds    s0, [r9]                    @ s0<- vA
5997
5998    fadds   s2, s0, s1                              @ s2<- op
5999    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6000    fsts    s2, [r9]                    @ vAA<- s2
6001    GOTO_OPCODE(ip)                     @ jump to next instruction
6002
6003
6004/* ------------------------------ */
6005    .balign 64
6006.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6007/* File: vfp/OP_SUB_FLOAT_2ADDR.S */
6008/* File: vfp/fbinop2addr.S */
6009    /*
6010     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6011     * an "instr" line that specifies an instruction that performs
6012     * "s2 = s0 op s1".
6013     *
6014     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6015     */
6016    /* binop/2addr vA, vB */
6017    mov     r3, rINST, lsr #12          @ r3<- B
6018    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6019    flds    s1, [r3]                    @ s1<- vB
6020    mov     r9, rINST, lsr #8           @ r9<- A+
6021    and     r9, r9, #15                 @ r9<- A
6022    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6023    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6024    flds    s0, [r9]                    @ s0<- vA
6025
6026    fsubs   s2, s0, s1                              @ s2<- op
6027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6028    fsts    s2, [r9]                    @ vAA<- s2
6029    GOTO_OPCODE(ip)                     @ jump to next instruction
6030
6031
6032/* ------------------------------ */
6033    .balign 64
6034.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6035/* File: vfp/OP_MUL_FLOAT_2ADDR.S */
6036/* File: vfp/fbinop2addr.S */
6037    /*
6038     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6039     * an "instr" line that specifies an instruction that performs
6040     * "s2 = s0 op s1".
6041     *
6042     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6043     */
6044    /* binop/2addr vA, vB */
6045    mov     r3, rINST, lsr #12          @ r3<- B
6046    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6047    flds    s1, [r3]                    @ s1<- vB
6048    mov     r9, rINST, lsr #8           @ r9<- A+
6049    and     r9, r9, #15                 @ r9<- A
6050    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6051    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6052    flds    s0, [r9]                    @ s0<- vA
6053
6054    fmuls   s2, s0, s1                              @ s2<- op
6055    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6056    fsts    s2, [r9]                    @ vAA<- s2
6057    GOTO_OPCODE(ip)                     @ jump to next instruction
6058
6059
6060/* ------------------------------ */
6061    .balign 64
6062.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6063/* File: vfp/OP_DIV_FLOAT_2ADDR.S */
6064/* File: vfp/fbinop2addr.S */
6065    /*
6066     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6067     * an "instr" line that specifies an instruction that performs
6068     * "s2 = s0 op s1".
6069     *
6070     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6071     */
6072    /* binop/2addr vA, vB */
6073    mov     r3, rINST, lsr #12          @ r3<- B
6074    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6075    flds    s1, [r3]                    @ s1<- vB
6076    mov     r9, rINST, lsr #8           @ r9<- A+
6077    and     r9, r9, #15                 @ r9<- A
6078    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6079    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6080    flds    s0, [r9]                    @ s0<- vA
6081
6082    fdivs   s2, s0, s1                              @ s2<- op
6083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6084    fsts    s2, [r9]                    @ vAA<- s2
6085    GOTO_OPCODE(ip)                     @ jump to next instruction
6086
6087
6088/* ------------------------------ */
6089    .balign 64
6090.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6091/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6092/* EABI doesn't define a float remainder function, but libm does */
6093/* File: armv5te/binop2addr.S */
6094    /*
6095     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6096     * that specifies an instruction that performs "result = r0 op r1".
6097     * This could be an ARM instruction or a function call.  (If the result
6098     * comes back in a register other than r0, you can override "result".)
6099     *
6100     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6101     * vCC (r1).  Useful for integer division and modulus.
6102     *
6103     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6104     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6105     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6106     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6107     */
6108    /* binop/2addr vA, vB */
6109    mov     r9, rINST, lsr #8           @ r9<- A+
6110    mov     r3, rINST, lsr #12          @ r3<- B
6111    and     r9, r9, #15
6112    GET_VREG(r0, r9)                    @ r0<- vA
6113    GET_VREG(r1, r3)                    @ r1<- vB
6114    .if 0
6115    cmp     r1, #0                      @ is second operand zero?
6116    beq     common_errDivideByZero
6117    .endif
6118    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6119
6120                               @ optional op; may set condition codes
6121    bl      fmodf                              @ r0<- op, r0-r3 changed
6122    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6123    SET_VREG(r0, r9)               @ vAA<- r0
6124    GOTO_OPCODE(ip)                     @ jump to next instruction
6125    /* 10-13 instructions */
6126
6127
6128
6129/* ------------------------------ */
6130    .balign 64
6131.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6132/* File: vfp/OP_ADD_DOUBLE_2ADDR.S */
6133/* File: vfp/fbinopWide2addr.S */
6134    /*
6135     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6136     * an "instr" line that specifies an instruction that performs
6137     * "d2 = d0 op d1".
6138     *
6139     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6140     *      div-double/2addr
6141     */
6142    /* binop/2addr vA, vB */
6143    mov     r3, rINST, lsr #12          @ r3<- B
6144    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6145    fldd    d1, [r3]                    @ d1<- vB
6146    mov     r9, rINST, lsr #8           @ r9<- A+
6147    and     r9, r9, #15                 @ r9<- A
6148    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6149    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6150    fldd    d0, [r9]                    @ d0<- vA
6151
6152    faddd   d2, d0, d1                              @ d2<- op
6153    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6154    fstd    d2, [r9]                    @ vAA<- d2
6155    GOTO_OPCODE(ip)                     @ jump to next instruction
6156
6157
6158/* ------------------------------ */
6159    .balign 64
6160.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6161/* File: vfp/OP_SUB_DOUBLE_2ADDR.S */
6162/* File: vfp/fbinopWide2addr.S */
6163    /*
6164     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6165     * an "instr" line that specifies an instruction that performs
6166     * "d2 = d0 op d1".
6167     *
6168     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6169     *      div-double/2addr
6170     */
6171    /* binop/2addr vA, vB */
6172    mov     r3, rINST, lsr #12          @ r3<- B
6173    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6174    fldd    d1, [r3]                    @ d1<- vB
6175    mov     r9, rINST, lsr #8           @ r9<- A+
6176    and     r9, r9, #15                 @ r9<- A
6177    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6178    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6179    fldd    d0, [r9]                    @ d0<- vA
6180
6181    fsubd   d2, d0, d1                              @ d2<- op
6182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6183    fstd    d2, [r9]                    @ vAA<- d2
6184    GOTO_OPCODE(ip)                     @ jump to next instruction
6185
6186
6187/* ------------------------------ */
6188    .balign 64
6189.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6190/* File: vfp/OP_MUL_DOUBLE_2ADDR.S */
6191/* File: vfp/fbinopWide2addr.S */
6192    /*
6193     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6194     * an "instr" line that specifies an instruction that performs
6195     * "d2 = d0 op d1".
6196     *
6197     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6198     *      div-double/2addr
6199     */
6200    /* binop/2addr vA, vB */
6201    mov     r3, rINST, lsr #12          @ r3<- B
6202    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6203    fldd    d1, [r3]                    @ d1<- vB
6204    mov     r9, rINST, lsr #8           @ r9<- A+
6205    and     r9, r9, #15                 @ r9<- A
6206    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6207    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6208    fldd    d0, [r9]                    @ d0<- vA
6209
6210    fmuld   d2, d0, d1                              @ d2<- op
6211    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6212    fstd    d2, [r9]                    @ vAA<- d2
6213    GOTO_OPCODE(ip)                     @ jump to next instruction
6214
6215
6216/* ------------------------------ */
6217    .balign 64
6218.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6219/* File: vfp/OP_DIV_DOUBLE_2ADDR.S */
6220/* File: vfp/fbinopWide2addr.S */
6221    /*
6222     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6223     * an "instr" line that specifies an instruction that performs
6224     * "d2 = d0 op d1".
6225     *
6226     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6227     *      div-double/2addr
6228     */
6229    /* binop/2addr vA, vB */
6230    mov     r3, rINST, lsr #12          @ r3<- B
6231    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6232    fldd    d1, [r3]                    @ d1<- vB
6233    mov     r9, rINST, lsr #8           @ r9<- A+
6234    and     r9, r9, #15                 @ r9<- A
6235    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6236    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6237    fldd    d0, [r9]                    @ d0<- vA
6238
6239    fdivd   d2, d0, d1                              @ d2<- op
6240    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6241    fstd    d2, [r9]                    @ vAA<- d2
6242    GOTO_OPCODE(ip)                     @ jump to next instruction
6243
6244
6245/* ------------------------------ */
6246    .balign 64
6247.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6248/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6249/* EABI doesn't define a double remainder function, but libm does */
6250/* File: armv5te/binopWide2addr.S */
6251    /*
6252     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6253     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6254     * This could be an ARM instruction or a function call.  (If the result
6255     * comes back in a register other than r0, you can override "result".)
6256     *
6257     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6258     * vCC (r1).  Useful for integer division and modulus.
6259     *
6260     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6261     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6262     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6263     *      rem-double/2addr
6264     */
6265    /* binop/2addr vA, vB */
6266    mov     r9, rINST, lsr #8           @ r9<- A+
6267    mov     r1, rINST, lsr #12          @ r1<- B
6268    and     r9, r9, #15
6269    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6270    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6271    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6272    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6273    .if 0
6274    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6275    beq     common_errDivideByZero
6276    .endif
6277    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6278
6279                               @ optional op; may set condition codes
6280    bl      fmod                              @ result<- op, r0-r3 changed
6281    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6282    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6283    GOTO_OPCODE(ip)                     @ jump to next instruction
6284    /* 12-15 instructions */
6285
6286
6287
6288/* ------------------------------ */
6289    .balign 64
6290.L_OP_ADD_INT_LIT16: /* 0xd0 */
6291/* File: armv5te/OP_ADD_INT_LIT16.S */
6292/* File: armv5te/binopLit16.S */
6293    /*
6294     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6295     * that specifies an instruction that performs "result = r0 op r1".
6296     * This could be an ARM instruction or a function call.  (If the result
6297     * comes back in a register other than r0, you can override "result".)
6298     *
6299     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6300     * vCC (r1).  Useful for integer division and modulus.
6301     *
6302     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6303     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6304     */
6305    /* binop/lit16 vA, vB, #+CCCC */
6306    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6307    mov     r2, rINST, lsr #12          @ r2<- B
6308    mov     r9, rINST, lsr #8           @ r9<- A+
6309    GET_VREG(r0, r2)                    @ r0<- vB
6310    and     r9, r9, #15
6311    .if 0
6312    cmp     r1, #0                      @ is second operand zero?
6313    beq     common_errDivideByZero
6314    .endif
6315    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6316
6317    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6318    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6319    SET_VREG(r0, r9)               @ vAA<- r0
6320    GOTO_OPCODE(ip)                     @ jump to next instruction
6321    /* 10-13 instructions */
6322
6323
6324
6325/* ------------------------------ */
6326    .balign 64
6327.L_OP_RSUB_INT: /* 0xd1 */
6328/* File: armv5te/OP_RSUB_INT.S */
6329/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6330/* File: armv5te/binopLit16.S */
6331    /*
6332     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6333     * that specifies an instruction that performs "result = r0 op r1".
6334     * This could be an ARM instruction or a function call.  (If the result
6335     * comes back in a register other than r0, you can override "result".)
6336     *
6337     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6338     * vCC (r1).  Useful for integer division and modulus.
6339     *
6340     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6341     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6342     */
6343    /* binop/lit16 vA, vB, #+CCCC */
6344    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6345    mov     r2, rINST, lsr #12          @ r2<- B
6346    mov     r9, rINST, lsr #8           @ r9<- A+
6347    GET_VREG(r0, r2)                    @ r0<- vB
6348    and     r9, r9, #15
6349    .if 0
6350    cmp     r1, #0                      @ is second operand zero?
6351    beq     common_errDivideByZero
6352    .endif
6353    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6354
6355    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6356    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6357    SET_VREG(r0, r9)               @ vAA<- r0
6358    GOTO_OPCODE(ip)                     @ jump to next instruction
6359    /* 10-13 instructions */
6360
6361
6362
6363/* ------------------------------ */
6364    .balign 64
6365.L_OP_MUL_INT_LIT16: /* 0xd2 */
6366/* File: armv5te/OP_MUL_INT_LIT16.S */
6367/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6368/* File: armv5te/binopLit16.S */
6369    /*
6370     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6371     * that specifies an instruction that performs "result = r0 op r1".
6372     * This could be an ARM instruction or a function call.  (If the result
6373     * comes back in a register other than r0, you can override "result".)
6374     *
6375     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6376     * vCC (r1).  Useful for integer division and modulus.
6377     *
6378     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6379     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6380     */
6381    /* binop/lit16 vA, vB, #+CCCC */
6382    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6383    mov     r2, rINST, lsr #12          @ r2<- B
6384    mov     r9, rINST, lsr #8           @ r9<- A+
6385    GET_VREG(r0, r2)                    @ r0<- vB
6386    and     r9, r9, #15
6387    .if 0
6388    cmp     r1, #0                      @ is second operand zero?
6389    beq     common_errDivideByZero
6390    .endif
6391    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6392
6393    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6394    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6395    SET_VREG(r0, r9)               @ vAA<- r0
6396    GOTO_OPCODE(ip)                     @ jump to next instruction
6397    /* 10-13 instructions */
6398
6399
6400
6401/* ------------------------------ */
6402    .balign 64
6403.L_OP_DIV_INT_LIT16: /* 0xd3 */
6404/* File: armv5te/OP_DIV_INT_LIT16.S */
6405/* File: armv5te/binopLit16.S */
6406    /*
6407     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6408     * that specifies an instruction that performs "result = r0 op r1".
6409     * This could be an ARM instruction or a function call.  (If the result
6410     * comes back in a register other than r0, you can override "result".)
6411     *
6412     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6413     * vCC (r1).  Useful for integer division and modulus.
6414     *
6415     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6416     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6417     */
6418    /* binop/lit16 vA, vB, #+CCCC */
6419    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6420    mov     r2, rINST, lsr #12          @ r2<- B
6421    mov     r9, rINST, lsr #8           @ r9<- A+
6422    GET_VREG(r0, r2)                    @ r0<- vB
6423    and     r9, r9, #15
6424    .if 1
6425    cmp     r1, #0                      @ is second operand zero?
6426    beq     common_errDivideByZero
6427    .endif
6428    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6429
6430    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6432    SET_VREG(r0, r9)               @ vAA<- r0
6433    GOTO_OPCODE(ip)                     @ jump to next instruction
6434    /* 10-13 instructions */
6435
6436
6437
6438/* ------------------------------ */
6439    .balign 64
6440.L_OP_REM_INT_LIT16: /* 0xd4 */
6441/* File: armv5te/OP_REM_INT_LIT16.S */
6442/* idivmod returns quotient in r0 and remainder in r1 */
6443/* File: armv5te/binopLit16.S */
6444    /*
6445     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6446     * that specifies an instruction that performs "result = r0 op r1".
6447     * This could be an ARM instruction or a function call.  (If the result
6448     * comes back in a register other than r0, you can override "result".)
6449     *
6450     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6451     * vCC (r1).  Useful for integer division and modulus.
6452     *
6453     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6454     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6455     */
6456    /* binop/lit16 vA, vB, #+CCCC */
6457    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6458    mov     r2, rINST, lsr #12          @ r2<- B
6459    mov     r9, rINST, lsr #8           @ r9<- A+
6460    GET_VREG(r0, r2)                    @ r0<- vB
6461    and     r9, r9, #15
6462    .if 1
6463    cmp     r1, #0                      @ is second operand zero?
6464    beq     common_errDivideByZero
6465    .endif
6466    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6467
6468    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6469    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6470    SET_VREG(r1, r9)               @ vAA<- r1
6471    GOTO_OPCODE(ip)                     @ jump to next instruction
6472    /* 10-13 instructions */
6473
6474
6475
6476/* ------------------------------ */
6477    .balign 64
6478.L_OP_AND_INT_LIT16: /* 0xd5 */
6479/* File: armv5te/OP_AND_INT_LIT16.S */
6480/* File: armv5te/binopLit16.S */
6481    /*
6482     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6483     * that specifies an instruction that performs "result = r0 op r1".
6484     * This could be an ARM instruction or a function call.  (If the result
6485     * comes back in a register other than r0, you can override "result".)
6486     *
6487     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6488     * vCC (r1).  Useful for integer division and modulus.
6489     *
6490     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6491     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6492     */
6493    /* binop/lit16 vA, vB, #+CCCC */
6494    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6495    mov     r2, rINST, lsr #12          @ r2<- B
6496    mov     r9, rINST, lsr #8           @ r9<- A+
6497    GET_VREG(r0, r2)                    @ r0<- vB
6498    and     r9, r9, #15
6499    .if 0
6500    cmp     r1, #0                      @ is second operand zero?
6501    beq     common_errDivideByZero
6502    .endif
6503    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6504
6505    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6506    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6507    SET_VREG(r0, r9)               @ vAA<- r0
6508    GOTO_OPCODE(ip)                     @ jump to next instruction
6509    /* 10-13 instructions */
6510
6511
6512
6513/* ------------------------------ */
6514    .balign 64
6515.L_OP_OR_INT_LIT16: /* 0xd6 */
6516/* File: armv5te/OP_OR_INT_LIT16.S */
6517/* File: armv5te/binopLit16.S */
6518    /*
6519     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6520     * that specifies an instruction that performs "result = r0 op r1".
6521     * This could be an ARM instruction or a function call.  (If the result
6522     * comes back in a register other than r0, you can override "result".)
6523     *
6524     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6525     * vCC (r1).  Useful for integer division and modulus.
6526     *
6527     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6528     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6529     */
6530    /* binop/lit16 vA, vB, #+CCCC */
6531    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6532    mov     r2, rINST, lsr #12          @ r2<- B
6533    mov     r9, rINST, lsr #8           @ r9<- A+
6534    GET_VREG(r0, r2)                    @ r0<- vB
6535    and     r9, r9, #15
6536    .if 0
6537    cmp     r1, #0                      @ is second operand zero?
6538    beq     common_errDivideByZero
6539    .endif
6540    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6541
6542    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6543    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6544    SET_VREG(r0, r9)               @ vAA<- r0
6545    GOTO_OPCODE(ip)                     @ jump to next instruction
6546    /* 10-13 instructions */
6547
6548
6549
6550/* ------------------------------ */
6551    .balign 64
6552.L_OP_XOR_INT_LIT16: /* 0xd7 */
6553/* File: armv5te/OP_XOR_INT_LIT16.S */
6554/* File: armv5te/binopLit16.S */
6555    /*
6556     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6557     * that specifies an instruction that performs "result = r0 op r1".
6558     * This could be an ARM instruction or a function call.  (If the result
6559     * comes back in a register other than r0, you can override "result".)
6560     *
6561     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6562     * vCC (r1).  Useful for integer division and modulus.
6563     *
6564     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6565     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6566     */
6567    /* binop/lit16 vA, vB, #+CCCC */
6568    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6569    mov     r2, rINST, lsr #12          @ r2<- B
6570    mov     r9, rINST, lsr #8           @ r9<- A+
6571    GET_VREG(r0, r2)                    @ r0<- vB
6572    and     r9, r9, #15
6573    .if 0
6574    cmp     r1, #0                      @ is second operand zero?
6575    beq     common_errDivideByZero
6576    .endif
6577    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6578
6579    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6581    SET_VREG(r0, r9)               @ vAA<- r0
6582    GOTO_OPCODE(ip)                     @ jump to next instruction
6583    /* 10-13 instructions */
6584
6585
6586
6587/* ------------------------------ */
6588    .balign 64
6589.L_OP_ADD_INT_LIT8: /* 0xd8 */
6590/* File: armv5te/OP_ADD_INT_LIT8.S */
6591/* File: armv5te/binopLit8.S */
6592    /*
6593     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6594     * that specifies an instruction that performs "result = r0 op r1".
6595     * This could be an ARM instruction or a function call.  (If the result
6596     * comes back in a register other than r0, you can override "result".)
6597     *
6598     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6599     * vCC (r1).  Useful for integer division and modulus.
6600     *
6601     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6602     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6603     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6604     */
6605    /* binop/lit8 vAA, vBB, #+CC */
6606    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6607    mov     r9, rINST, lsr #8           @ r9<- AA
6608    and     r2, r3, #255                @ r2<- BB
6609    GET_VREG(r0, r2)                    @ r0<- vBB
6610    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6611    .if 0
6612    @cmp     r1, #0                      @ is second operand zero?
6613    beq     common_errDivideByZero
6614    .endif
6615    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6616
6617                               @ optional op; may set condition codes
6618    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6620    SET_VREG(r0, r9)               @ vAA<- r0
6621    GOTO_OPCODE(ip)                     @ jump to next instruction
6622    /* 10-12 instructions */
6623
6624
6625
6626/* ------------------------------ */
6627    .balign 64
6628.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6629/* File: armv5te/OP_RSUB_INT_LIT8.S */
6630/* File: armv5te/binopLit8.S */
6631    /*
6632     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6633     * that specifies an instruction that performs "result = r0 op r1".
6634     * This could be an ARM instruction or a function call.  (If the result
6635     * comes back in a register other than r0, you can override "result".)
6636     *
6637     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6638     * vCC (r1).  Useful for integer division and modulus.
6639     *
6640     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6641     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6642     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6643     */
6644    /* binop/lit8 vAA, vBB, #+CC */
6645    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6646    mov     r9, rINST, lsr #8           @ r9<- AA
6647    and     r2, r3, #255                @ r2<- BB
6648    GET_VREG(r0, r2)                    @ r0<- vBB
6649    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6650    .if 0
6651    @cmp     r1, #0                      @ is second operand zero?
6652    beq     common_errDivideByZero
6653    .endif
6654    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6655
6656                               @ optional op; may set condition codes
6657    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6658    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6659    SET_VREG(r0, r9)               @ vAA<- r0
6660    GOTO_OPCODE(ip)                     @ jump to next instruction
6661    /* 10-12 instructions */
6662
6663
6664
6665/* ------------------------------ */
6666    .balign 64
6667.L_OP_MUL_INT_LIT8: /* 0xda */
6668/* File: armv5te/OP_MUL_INT_LIT8.S */
6669/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6670/* File: armv5te/binopLit8.S */
6671    /*
6672     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6673     * that specifies an instruction that performs "result = r0 op r1".
6674     * This could be an ARM instruction or a function call.  (If the result
6675     * comes back in a register other than r0, you can override "result".)
6676     *
6677     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6678     * vCC (r1).  Useful for integer division and modulus.
6679     *
6680     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6681     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6682     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6683     */
6684    /* binop/lit8 vAA, vBB, #+CC */
6685    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6686    mov     r9, rINST, lsr #8           @ r9<- AA
6687    and     r2, r3, #255                @ r2<- BB
6688    GET_VREG(r0, r2)                    @ r0<- vBB
6689    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6690    .if 0
6691    @cmp     r1, #0                      @ is second operand zero?
6692    beq     common_errDivideByZero
6693    .endif
6694    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6695
6696                               @ optional op; may set condition codes
6697    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6698    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6699    SET_VREG(r0, r9)               @ vAA<- r0
6700    GOTO_OPCODE(ip)                     @ jump to next instruction
6701    /* 10-12 instructions */
6702
6703
6704
6705/* ------------------------------ */
6706    .balign 64
6707.L_OP_DIV_INT_LIT8: /* 0xdb */
6708/* File: armv5te/OP_DIV_INT_LIT8.S */
6709/* File: armv5te/binopLit8.S */
6710    /*
6711     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6712     * that specifies an instruction that performs "result = r0 op r1".
6713     * This could be an ARM instruction or a function call.  (If the result
6714     * comes back in a register other than r0, you can override "result".)
6715     *
6716     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6717     * vCC (r1).  Useful for integer division and modulus.
6718     *
6719     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6720     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6721     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6722     */
6723    /* binop/lit8 vAA, vBB, #+CC */
6724    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6725    mov     r9, rINST, lsr #8           @ r9<- AA
6726    and     r2, r3, #255                @ r2<- BB
6727    GET_VREG(r0, r2)                    @ r0<- vBB
6728    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6729    .if 1
6730    @cmp     r1, #0                      @ is second operand zero?
6731    beq     common_errDivideByZero
6732    .endif
6733    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6734
6735                               @ optional op; may set condition codes
6736    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6737    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6738    SET_VREG(r0, r9)               @ vAA<- r0
6739    GOTO_OPCODE(ip)                     @ jump to next instruction
6740    /* 10-12 instructions */
6741
6742
6743
6744/* ------------------------------ */
6745    .balign 64
6746.L_OP_REM_INT_LIT8: /* 0xdc */
6747/* File: armv5te/OP_REM_INT_LIT8.S */
6748/* idivmod returns quotient in r0 and remainder in r1 */
6749/* File: armv5te/binopLit8.S */
6750    /*
6751     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6752     * that specifies an instruction that performs "result = r0 op r1".
6753     * This could be an ARM instruction or a function call.  (If the result
6754     * comes back in a register other than r0, you can override "result".)
6755     *
6756     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6757     * vCC (r1).  Useful for integer division and modulus.
6758     *
6759     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6760     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6761     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6762     */
6763    /* binop/lit8 vAA, vBB, #+CC */
6764    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6765    mov     r9, rINST, lsr #8           @ r9<- AA
6766    and     r2, r3, #255                @ r2<- BB
6767    GET_VREG(r0, r2)                    @ r0<- vBB
6768    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6769    .if 1
6770    @cmp     r1, #0                      @ is second operand zero?
6771    beq     common_errDivideByZero
6772    .endif
6773    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6774
6775                               @ optional op; may set condition codes
6776    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6777    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6778    SET_VREG(r1, r9)               @ vAA<- r1
6779    GOTO_OPCODE(ip)                     @ jump to next instruction
6780    /* 10-12 instructions */
6781
6782
6783
6784/* ------------------------------ */
6785    .balign 64
6786.L_OP_AND_INT_LIT8: /* 0xdd */
6787/* File: armv5te/OP_AND_INT_LIT8.S */
6788/* File: armv5te/binopLit8.S */
6789    /*
6790     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6791     * that specifies an instruction that performs "result = r0 op r1".
6792     * This could be an ARM instruction or a function call.  (If the result
6793     * comes back in a register other than r0, you can override "result".)
6794     *
6795     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6796     * vCC (r1).  Useful for integer division and modulus.
6797     *
6798     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6799     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6800     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6801     */
6802    /* binop/lit8 vAA, vBB, #+CC */
6803    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6804    mov     r9, rINST, lsr #8           @ r9<- AA
6805    and     r2, r3, #255                @ r2<- BB
6806    GET_VREG(r0, r2)                    @ r0<- vBB
6807    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6808    .if 0
6809    @cmp     r1, #0                      @ is second operand zero?
6810    beq     common_errDivideByZero
6811    .endif
6812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6813
6814                               @ optional op; may set condition codes
6815    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6817    SET_VREG(r0, r9)               @ vAA<- r0
6818    GOTO_OPCODE(ip)                     @ jump to next instruction
6819    /* 10-12 instructions */
6820
6821
6822
6823/* ------------------------------ */
6824    .balign 64
6825.L_OP_OR_INT_LIT8: /* 0xde */
6826/* File: armv5te/OP_OR_INT_LIT8.S */
6827/* File: armv5te/binopLit8.S */
6828    /*
6829     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6830     * that specifies an instruction that performs "result = r0 op r1".
6831     * This could be an ARM instruction or a function call.  (If the result
6832     * comes back in a register other than r0, you can override "result".)
6833     *
6834     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6835     * vCC (r1).  Useful for integer division and modulus.
6836     *
6837     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6838     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6839     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6840     */
6841    /* binop/lit8 vAA, vBB, #+CC */
6842    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6843    mov     r9, rINST, lsr #8           @ r9<- AA
6844    and     r2, r3, #255                @ r2<- BB
6845    GET_VREG(r0, r2)                    @ r0<- vBB
6846    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6847    .if 0
6848    @cmp     r1, #0                      @ is second operand zero?
6849    beq     common_errDivideByZero
6850    .endif
6851    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6852
6853                               @ optional op; may set condition codes
6854    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6856    SET_VREG(r0, r9)               @ vAA<- r0
6857    GOTO_OPCODE(ip)                     @ jump to next instruction
6858    /* 10-12 instructions */
6859
6860
6861
6862/* ------------------------------ */
6863    .balign 64
6864.L_OP_XOR_INT_LIT8: /* 0xdf */
6865/* File: armv5te/OP_XOR_INT_LIT8.S */
6866/* File: armv5te/binopLit8.S */
6867    /*
6868     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6869     * that specifies an instruction that performs "result = r0 op r1".
6870     * This could be an ARM instruction or a function call.  (If the result
6871     * comes back in a register other than r0, you can override "result".)
6872     *
6873     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6874     * vCC (r1).  Useful for integer division and modulus.
6875     *
6876     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6877     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6878     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6879     */
6880    /* binop/lit8 vAA, vBB, #+CC */
6881    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6882    mov     r9, rINST, lsr #8           @ r9<- AA
6883    and     r2, r3, #255                @ r2<- BB
6884    GET_VREG(r0, r2)                    @ r0<- vBB
6885    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6886    .if 0
6887    @cmp     r1, #0                      @ is second operand zero?
6888    beq     common_errDivideByZero
6889    .endif
6890    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6891
6892                               @ optional op; may set condition codes
6893    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6894    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6895    SET_VREG(r0, r9)               @ vAA<- r0
6896    GOTO_OPCODE(ip)                     @ jump to next instruction
6897    /* 10-12 instructions */
6898
6899
6900
6901/* ------------------------------ */
6902    .balign 64
6903.L_OP_SHL_INT_LIT8: /* 0xe0 */
6904/* File: armv5te/OP_SHL_INT_LIT8.S */
6905/* File: armv5te/binopLit8.S */
6906    /*
6907     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6908     * that specifies an instruction that performs "result = r0 op r1".
6909     * This could be an ARM instruction or a function call.  (If the result
6910     * comes back in a register other than r0, you can override "result".)
6911     *
6912     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6913     * vCC (r1).  Useful for integer division and modulus.
6914     *
6915     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6916     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6917     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6918     */
6919    /* binop/lit8 vAA, vBB, #+CC */
6920    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6921    mov     r9, rINST, lsr #8           @ r9<- AA
6922    and     r2, r3, #255                @ r2<- BB
6923    GET_VREG(r0, r2)                    @ r0<- vBB
6924    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6925    .if 0
6926    @cmp     r1, #0                      @ is second operand zero?
6927    beq     common_errDivideByZero
6928    .endif
6929    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6930
6931    and     r1, r1, #31                           @ optional op; may set condition codes
6932    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
6933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6934    SET_VREG(r0, r9)               @ vAA<- r0
6935    GOTO_OPCODE(ip)                     @ jump to next instruction
6936    /* 10-12 instructions */
6937
6938
6939
6940/* ------------------------------ */
6941    .balign 64
6942.L_OP_SHR_INT_LIT8: /* 0xe1 */
6943/* File: armv5te/OP_SHR_INT_LIT8.S */
6944/* File: armv5te/binopLit8.S */
6945    /*
6946     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6947     * that specifies an instruction that performs "result = r0 op r1".
6948     * This could be an ARM instruction or a function call.  (If the result
6949     * comes back in a register other than r0, you can override "result".)
6950     *
6951     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6952     * vCC (r1).  Useful for integer division and modulus.
6953     *
6954     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6955     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6956     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6957     */
6958    /* binop/lit8 vAA, vBB, #+CC */
6959    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6960    mov     r9, rINST, lsr #8           @ r9<- AA
6961    and     r2, r3, #255                @ r2<- BB
6962    GET_VREG(r0, r2)                    @ r0<- vBB
6963    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6964    .if 0
6965    @cmp     r1, #0                      @ is second operand zero?
6966    beq     common_errDivideByZero
6967    .endif
6968    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6969
6970    and     r1, r1, #31                           @ optional op; may set condition codes
6971    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
6972    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6973    SET_VREG(r0, r9)               @ vAA<- r0
6974    GOTO_OPCODE(ip)                     @ jump to next instruction
6975    /* 10-12 instructions */
6976
6977
6978
6979/* ------------------------------ */
6980    .balign 64
6981.L_OP_USHR_INT_LIT8: /* 0xe2 */
6982/* File: armv5te/OP_USHR_INT_LIT8.S */
6983/* File: armv5te/binopLit8.S */
6984    /*
6985     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6986     * that specifies an instruction that performs "result = r0 op r1".
6987     * This could be an ARM instruction or a function call.  (If the result
6988     * comes back in a register other than r0, you can override "result".)
6989     *
6990     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6991     * vCC (r1).  Useful for integer division and modulus.
6992     *
6993     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6994     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6995     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6996     */
6997    /* binop/lit8 vAA, vBB, #+CC */
6998    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6999    mov     r9, rINST, lsr #8           @ r9<- AA
7000    and     r2, r3, #255                @ r2<- BB
7001    GET_VREG(r0, r2)                    @ r0<- vBB
7002    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7003    .if 0
7004    @cmp     r1, #0                      @ is second operand zero?
7005    beq     common_errDivideByZero
7006    .endif
7007    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7008
7009    and     r1, r1, #31                           @ optional op; may set condition codes
7010    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7011    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7012    SET_VREG(r0, r9)               @ vAA<- r0
7013    GOTO_OPCODE(ip)                     @ jump to next instruction
7014    /* 10-12 instructions */
7015
7016
7017
7018/* ------------------------------ */
7019    .balign 64
7020.L_OP_UNUSED_E3: /* 0xe3 */
7021/* File: armv5te/OP_UNUSED_E3.S */
7022/* File: armv5te/unused.S */
7023    bl      common_abort
7024
7025
7026
7027/* ------------------------------ */
7028    .balign 64
7029.L_OP_UNUSED_E4: /* 0xe4 */
7030/* File: armv5te/OP_UNUSED_E4.S */
7031/* File: armv5te/unused.S */
7032    bl      common_abort
7033
7034
7035
7036/* ------------------------------ */
7037    .balign 64
7038.L_OP_UNUSED_E5: /* 0xe5 */
7039/* File: armv5te/OP_UNUSED_E5.S */
7040/* File: armv5te/unused.S */
7041    bl      common_abort
7042
7043
7044
7045/* ------------------------------ */
7046    .balign 64
7047.L_OP_UNUSED_E6: /* 0xe6 */
7048/* File: armv5te/OP_UNUSED_E6.S */
7049/* File: armv5te/unused.S */
7050    bl      common_abort
7051
7052
7053
7054/* ------------------------------ */
7055    .balign 64
7056.L_OP_UNUSED_E7: /* 0xe7 */
7057/* File: armv5te/OP_UNUSED_E7.S */
7058/* File: armv5te/unused.S */
7059    bl      common_abort
7060
7061
7062
7063/* ------------------------------ */
7064    .balign 64
7065.L_OP_UNUSED_E8: /* 0xe8 */
7066/* File: armv5te/OP_UNUSED_E8.S */
7067/* File: armv5te/unused.S */
7068    bl      common_abort
7069
7070
7071
7072/* ------------------------------ */
7073    .balign 64
7074.L_OP_UNUSED_E9: /* 0xe9 */
7075/* File: armv5te/OP_UNUSED_E9.S */
7076/* File: armv5te/unused.S */
7077    bl      common_abort
7078
7079
7080
7081/* ------------------------------ */
7082    .balign 64
7083.L_OP_UNUSED_EA: /* 0xea */
7084/* File: armv5te/OP_UNUSED_EA.S */
7085/* File: armv5te/unused.S */
7086    bl      common_abort
7087
7088
7089
7090/* ------------------------------ */
7091    .balign 64
7092.L_OP_UNUSED_EB: /* 0xeb */
7093/* File: armv5te/OP_UNUSED_EB.S */
7094/* File: armv5te/unused.S */
7095    bl      common_abort
7096
7097
7098
7099/* ------------------------------ */
7100    .balign 64
7101.L_OP_UNUSED_EC: /* 0xec */
7102/* File: armv5te/OP_UNUSED_EC.S */
7103/* File: armv5te/unused.S */
7104    bl      common_abort
7105
7106
7107
7108/* ------------------------------ */
7109    .balign 64
7110.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7111/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7112    /*
7113     * Handle a throw-verification-error instruction.  This throws an
7114     * exception for an error discovered during verification.  The
7115     * exception is indicated by AA, with some detail provided by BBBB.
7116     */
7117    /* op AA, ref@BBBB */
7118    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7119    FETCH(r2, 1)                        @ r2<- BBBB
7120    EXPORT_PC()                         @ export the PC
7121    mov     r1, rINST, lsr #8           @ r1<- AA
7122    bl      dvmThrowVerificationError   @ always throws
7123    b       common_exceptionThrown      @ handle exception
7124
7125
7126/* ------------------------------ */
7127    .balign 64
7128.L_OP_EXECUTE_INLINE: /* 0xee */
7129/* File: armv5te/OP_EXECUTE_INLINE.S */
7130    /*
7131     * Execute a "native inline" instruction.
7132     *
7133     * We need to call:
7134     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7135     *
7136     * The first four args are in r0-r3, but the last two must be pushed
7137     * onto the stack.
7138     */
7139    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7140    FETCH(r10, 1)                       @ r10<- BBBB
7141    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7142    EXPORT_PC()                         @ can throw
7143    sub     sp, sp, #8                  @ make room for arg(s)
7144    mov     r0, rINST, lsr #12          @ r0<- B
7145    str     r1, [sp]                    @ push &glue->retval
7146    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7147    add     sp, sp, #8                  @ pop stack
7148    cmp     r0, #0                      @ test boolean result of inline
7149    beq     common_exceptionThrown      @ returned false, handle exception
7150    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7152    GOTO_OPCODE(ip)                     @ jump to next instruction
7153
7154/* ------------------------------ */
7155    .balign 64
7156.L_OP_UNUSED_EF: /* 0xef */
7157/* File: armv5te/OP_UNUSED_EF.S */
7158/* File: armv5te/unused.S */
7159    bl      common_abort
7160
7161
7162
7163/* ------------------------------ */
7164    .balign 64
7165.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7166/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7167    /*
7168     * invoke-direct-empty is a no-op in a "standard" interpreter.
7169     */
7170    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7171    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7172    GOTO_OPCODE(ip)                     @ execute it
7173
7174/* ------------------------------ */
7175    .balign 64
7176.L_OP_UNUSED_F1: /* 0xf1 */
7177/* File: armv5te/OP_UNUSED_F1.S */
7178/* File: armv5te/unused.S */
7179    bl      common_abort
7180
7181
7182
7183/* ------------------------------ */
7184    .balign 64
7185.L_OP_IGET_QUICK: /* 0xf2 */
7186/* File: armv5te/OP_IGET_QUICK.S */
7187    /* For: iget-quick, iget-object-quick */
7188    /* op vA, vB, offset@CCCC */
7189    mov     r2, rINST, lsr #12          @ r2<- B
7190    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7191    FETCH(r1, 1)                        @ r1<- field byte offset
7192    cmp     r3, #0                      @ check object for null
7193    mov     r2, rINST, lsr #8           @ r2<- A(+)
7194    beq     common_errNullObject        @ object was null
7195    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7196    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7197    and     r2, r2, #15
7198    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7199    SET_VREG(r0, r2)                    @ fp[A]<- r0
7200    GOTO_OPCODE(ip)                     @ jump to next instruction
7201
7202
7203/* ------------------------------ */
7204    .balign 64
7205.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7206/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7207    /* iget-wide-quick vA, vB, offset@CCCC */
7208    mov     r2, rINST, lsr #12          @ r2<- B
7209    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7210    FETCH(r1, 1)                        @ r1<- field byte offset
7211    cmp     r3, #0                      @ check object for null
7212    mov     r2, rINST, lsr #8           @ r2<- A(+)
7213    beq     common_errNullObject        @ object was null
7214    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7215    and     r2, r2, #15
7216    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7217    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7219    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7220    GOTO_OPCODE(ip)                     @ jump to next instruction
7221
7222
7223/* ------------------------------ */
7224    .balign 64
7225.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7226/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7227/* File: armv5te/OP_IGET_QUICK.S */
7228    /* For: iget-quick, iget-object-quick */
7229    /* op vA, vB, offset@CCCC */
7230    mov     r2, rINST, lsr #12          @ r2<- B
7231    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7232    FETCH(r1, 1)                        @ r1<- field byte offset
7233    cmp     r3, #0                      @ check object for null
7234    mov     r2, rINST, lsr #8           @ r2<- A(+)
7235    beq     common_errNullObject        @ object was null
7236    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7237    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7238    and     r2, r2, #15
7239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7240    SET_VREG(r0, r2)                    @ fp[A]<- r0
7241    GOTO_OPCODE(ip)                     @ jump to next instruction
7242
7243
7244
7245/* ------------------------------ */
7246    .balign 64
7247.L_OP_IPUT_QUICK: /* 0xf5 */
7248/* File: armv5te/OP_IPUT_QUICK.S */
7249    /* For: iput-quick, iput-object-quick */
7250    /* op vA, vB, offset@CCCC */
7251    mov     r2, rINST, lsr #12          @ r2<- B
7252    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7253    FETCH(r1, 1)                        @ r1<- field byte offset
7254    cmp     r3, #0                      @ check object for null
7255    mov     r2, rINST, lsr #8           @ r2<- A(+)
7256    beq     common_errNullObject        @ object was null
7257    and     r2, r2, #15
7258    GET_VREG(r0, r2)                    @ r0<- fp[A]
7259    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7260    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7261    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7262    GOTO_OPCODE(ip)                     @ jump to next instruction
7263
7264
7265/* ------------------------------ */
7266    .balign 64
7267.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7268/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7269    /* iput-wide-quick vA, vB, offset@CCCC */
7270    mov     r0, rINST, lsr #8           @ r0<- A(+)
7271    mov     r1, rINST, lsr #12          @ r1<- B
7272    and     r0, r0, #15
7273    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7274    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7275    cmp     r2, #0                      @ check object for null
7276    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7277    beq     common_errNullObject        @ object was null
7278    FETCH(r3, 1)                        @ r3<- field byte offset
7279    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7280    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7281    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7282    GOTO_OPCODE(ip)                     @ jump to next instruction
7283
7284
7285/* ------------------------------ */
7286    .balign 64
7287.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7288/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7289/* File: armv5te/OP_IPUT_QUICK.S */
7290    /* For: iput-quick, iput-object-quick */
7291    /* op vA, vB, offset@CCCC */
7292    mov     r2, rINST, lsr #12          @ r2<- B
7293    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7294    FETCH(r1, 1)                        @ r1<- field byte offset
7295    cmp     r3, #0                      @ check object for null
7296    mov     r2, rINST, lsr #8           @ r2<- A(+)
7297    beq     common_errNullObject        @ object was null
7298    and     r2, r2, #15
7299    GET_VREG(r0, r2)                    @ r0<- fp[A]
7300    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7301    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7303    GOTO_OPCODE(ip)                     @ jump to next instruction
7304
7305
7306
7307/* ------------------------------ */
7308    .balign 64
7309.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7310/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7311    /*
7312     * Handle an optimized virtual method call.
7313     *
7314     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7315     */
7316    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7317    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7318    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7319    FETCH(r1, 1)                        @ r1<- BBBB
7320    .if     (!0)
7321    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7322    .endif
7323    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7324    cmp     r2, #0                      @ is "this" null?
7325    beq     common_errNullObject        @ null "this", throw exception
7326    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7327    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7328    EXPORT_PC()                         @ invoke must export
7329    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7330    bl      common_invokeMethodNoRange @ continue on
7331
7332/* ------------------------------ */
7333    .balign 64
7334.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7335/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7336/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7337    /*
7338     * Handle an optimized virtual method call.
7339     *
7340     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7341     */
7342    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7343    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7344    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7345    FETCH(r1, 1)                        @ r1<- BBBB
7346    .if     (!1)
7347    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7348    .endif
7349    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7350    cmp     r2, #0                      @ is "this" null?
7351    beq     common_errNullObject        @ null "this", throw exception
7352    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7353    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7354    EXPORT_PC()                         @ invoke must export
7355    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7356    bl      common_invokeMethodRange @ continue on
7357
7358
7359/* ------------------------------ */
7360    .balign 64
7361.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7362/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7363    /*
7364     * Handle an optimized "super" method call.
7365     *
7366     * for: [opt] invoke-super-quick, invoke-super-quick/range
7367     */
7368    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7369    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7370    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7371    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7372    .if     (!0)
7373    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7374    .endif
7375    FETCH(r1, 1)                        @ r1<- BBBB
7376    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7377    EXPORT_PC()                         @ must export for invoke
7378    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7379    GET_VREG(r3, r10)                   @ r3<- "this"
7380    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7381    cmp     r3, #0                      @ null "this" ref?
7382    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7383    beq     common_errNullObject        @ "this" is null, throw exception
7384    bl      common_invokeMethodNoRange @ continue on
7385
7386
7387/* ------------------------------ */
7388    .balign 64
7389.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7390/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7391/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7392    /*
7393     * Handle an optimized "super" method call.
7394     *
7395     * for: [opt] invoke-super-quick, invoke-super-quick/range
7396     */
7397    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7398    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7399    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7400    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7401    .if     (!1)
7402    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7403    .endif
7404    FETCH(r1, 1)                        @ r1<- BBBB
7405    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7406    EXPORT_PC()                         @ must export for invoke
7407    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7408    GET_VREG(r3, r10)                   @ r3<- "this"
7409    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7410    cmp     r3, #0                      @ null "this" ref?
7411    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7412    beq     common_errNullObject        @ "this" is null, throw exception
7413    bl      common_invokeMethodRange @ continue on
7414
7415
7416
7417/* ------------------------------ */
7418    .balign 64
7419.L_OP_UNUSED_FC: /* 0xfc */
7420/* File: armv5te/OP_UNUSED_FC.S */
7421/* File: armv5te/unused.S */
7422    bl      common_abort
7423
7424
7425
7426/* ------------------------------ */
7427    .balign 64
7428.L_OP_UNUSED_FD: /* 0xfd */
7429/* File: armv5te/OP_UNUSED_FD.S */
7430/* File: armv5te/unused.S */
7431    bl      common_abort
7432
7433
7434
7435/* ------------------------------ */
7436    .balign 64
7437.L_OP_UNUSED_FE: /* 0xfe */
7438/* File: armv5te/OP_UNUSED_FE.S */
7439/* File: armv5te/unused.S */
7440    bl      common_abort
7441
7442
7443
7444/* ------------------------------ */
7445    .balign 64
7446.L_OP_UNUSED_FF: /* 0xff */
7447/* File: armv5te/OP_UNUSED_FF.S */
7448/* File: armv5te/unused.S */
7449    bl      common_abort
7450
7451
7452
7453
7454    .balign 64
7455    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7456    .global dvmAsmInstructionEnd
7457dvmAsmInstructionEnd:
7458
7459/*
7460 * ===========================================================================
7461 *  Sister implementations
7462 * ===========================================================================
7463 */
7464    .global dvmAsmSisterStart
7465    .type   dvmAsmSisterStart, %function
7466    .text
7467    .balign 4
7468dvmAsmSisterStart:
7469
7470/* continuation for OP_CONST_STRING */
7471
7472    /*
7473     * Continuation if the String has not yet been resolved.
7474     *  r1: BBBB (String ref)
7475     *  r9: target register
7476     */
7477.LOP_CONST_STRING_resolve:
7478    EXPORT_PC()
7479    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7480    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7481    bl      dvmResolveString            @ r0<- String reference
7482    cmp     r0, #0                      @ failed?
7483    beq     common_exceptionThrown      @ yup, handle the exception
7484    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7486    SET_VREG(r0, r9)                    @ vAA<- r0
7487    GOTO_OPCODE(ip)                     @ jump to next instruction
7488
7489
7490/* continuation for OP_CONST_STRING_JUMBO */
7491
7492    /*
7493     * Continuation if the String has not yet been resolved.
7494     *  r1: BBBBBBBB (String ref)
7495     *  r9: target register
7496     */
7497.LOP_CONST_STRING_JUMBO_resolve:
7498    EXPORT_PC()
7499    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7500    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7501    bl      dvmResolveString            @ r0<- String reference
7502    cmp     r0, #0                      @ failed?
7503    beq     common_exceptionThrown      @ yup, handle the exception
7504    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7506    SET_VREG(r0, r9)                    @ vAA<- r0
7507    GOTO_OPCODE(ip)                     @ jump to next instruction
7508
7509
7510/* continuation for OP_CONST_CLASS */
7511
7512    /*
7513     * Continuation if the Class has not yet been resolved.
7514     *  r1: BBBB (Class ref)
7515     *  r9: target register
7516     */
7517.LOP_CONST_CLASS_resolve:
7518    EXPORT_PC()
7519    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7520    mov     r2, #1                      @ r2<- true
7521    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7522    bl      dvmResolveClass             @ r0<- Class reference
7523    cmp     r0, #0                      @ failed?
7524    beq     common_exceptionThrown      @ yup, handle the exception
7525    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7526    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7527    SET_VREG(r0, r9)                    @ vAA<- r0
7528    GOTO_OPCODE(ip)                     @ jump to next instruction
7529
7530
7531/* continuation for OP_CHECK_CAST */
7532
7533    /*
7534     * Trivial test failed, need to perform full check.  This is common.
7535     *  r0 holds obj->clazz
7536     *  r1 holds class resolved from BBBB
7537     *  r9 holds object
7538     */
7539.LOP_CHECK_CAST_fullcheck:
7540    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7541    cmp     r0, #0                      @ failed?
7542    bne     .LOP_CHECK_CAST_okay            @ no, success
7543
7544    @ A cast has failed.  We need to throw a ClassCastException with the
7545    @ class of the object that failed to be cast.
7546    EXPORT_PC()                         @ about to throw
7547    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7548    ldr     r0, .LstrClassCastExceptionPtr
7549    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7550    bl      dvmThrowExceptionWithClassMessage
7551    b       common_exceptionThrown
7552
7553    /*
7554     * Resolution required.  This is the least-likely path.
7555     *
7556     *  r2 holds BBBB
7557     *  r9 holds object
7558     */
7559.LOP_CHECK_CAST_resolve:
7560    EXPORT_PC()                         @ resolve() could throw
7561    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7562    mov     r1, r2                      @ r1<- BBBB
7563    mov     r2, #0                      @ r2<- false
7564    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7565    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7566    cmp     r0, #0                      @ got null?
7567    beq     common_exceptionThrown      @ yes, handle exception
7568    mov     r1, r0                      @ r1<- class resolved from BBB
7569    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7570    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7571
7572.LstrClassCastExceptionPtr:
7573    .word   .LstrClassCastException
7574
7575
7576/* continuation for OP_INSTANCE_OF */
7577
7578    /*
7579     * Trivial test failed, need to perform full check.  This is common.
7580     *  r0 holds obj->clazz
7581     *  r1 holds class resolved from BBBB
7582     *  r9 holds A
7583     */
7584.LOP_INSTANCE_OF_fullcheck:
7585    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7586    @ fall through to OP_INSTANCE_OF_store
7587
7588    /*
7589     * r0 holds boolean result
7590     * r9 holds A
7591     */
7592.LOP_INSTANCE_OF_store:
7593    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7594    SET_VREG(r0, r9)                    @ vA<- r0
7595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7596    GOTO_OPCODE(ip)                     @ jump to next instruction
7597
7598    /*
7599     * Trivial test succeeded, save and bail.
7600     *  r9 holds A
7601     */
7602.LOP_INSTANCE_OF_trivial:
7603    mov     r0, #1                      @ indicate success
7604    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7605    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7606    SET_VREG(r0, r9)                    @ vA<- r0
7607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7608    GOTO_OPCODE(ip)                     @ jump to next instruction
7609
7610    /*
7611     * Resolution required.  This is the least-likely path.
7612     *
7613     *  r3 holds BBBB
7614     *  r9 holds A
7615     */
7616.LOP_INSTANCE_OF_resolve:
7617    EXPORT_PC()                         @ resolve() could throw
7618    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7619    mov     r1, r3                      @ r1<- BBBB
7620    mov     r2, #1                      @ r2<- true
7621    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7622    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7623    cmp     r0, #0                      @ got null?
7624    beq     common_exceptionThrown      @ yes, handle exception
7625    mov     r1, r0                      @ r1<- class resolved from BBB
7626    mov     r3, rINST, lsr #12          @ r3<- B
7627    GET_VREG(r0, r3)                    @ r0<- vB (object)
7628    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7629    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7630
7631
7632/* continuation for OP_NEW_INSTANCE */
7633
7634    .balign 32                          @ minimize cache lines
7635.LOP_NEW_INSTANCE_finish: @ r0=new object
7636    mov     r3, rINST, lsr #8           @ r3<- AA
7637    cmp     r0, #0                      @ failed?
7638    beq     common_exceptionThrown      @ yes, handle the exception
7639    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7641    SET_VREG(r0, r3)                    @ vAA<- r0
7642    GOTO_OPCODE(ip)                     @ jump to next instruction
7643
7644    /*
7645     * Class initialization required.
7646     *
7647     *  r0 holds class object
7648     */
7649.LOP_NEW_INSTANCE_needinit:
7650    mov     r9, r0                      @ save r0
7651    bl      dvmInitClass                @ initialize class
7652    cmp     r0, #0                      @ check boolean result
7653    mov     r0, r9                      @ restore r0
7654    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7655    b       common_exceptionThrown      @ failed, deal with init exception
7656
7657    /*
7658     * Resolution required.  This is the least-likely path.
7659     *
7660     *  r1 holds BBBB
7661     */
7662.LOP_NEW_INSTANCE_resolve:
7663    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7664    mov     r2, #0                      @ r2<- false
7665    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7666    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7667    cmp     r0, #0                      @ got null?
7668    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7669    b       common_exceptionThrown      @ yes, handle exception
7670
7671.LstrInstantiationErrorPtr:
7672    .word   .LstrInstantiationError
7673
7674
7675/* continuation for OP_NEW_ARRAY */
7676
7677
7678    /*
7679     * Resolve class.  (This is an uncommon case.)
7680     *
7681     *  r1 holds array length
7682     *  r2 holds class ref CCCC
7683     */
7684.LOP_NEW_ARRAY_resolve:
7685    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7686    mov     r9, r1                      @ r9<- length (save)
7687    mov     r1, r2                      @ r1<- CCCC
7688    mov     r2, #0                      @ r2<- false
7689    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7690    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7691    cmp     r0, #0                      @ got null?
7692    mov     r1, r9                      @ r1<- length (restore)
7693    beq     common_exceptionThrown      @ yes, handle exception
7694    @ fall through to OP_NEW_ARRAY_finish
7695
7696    /*
7697     * Finish allocation.
7698     *
7699     *  r0 holds class
7700     *  r1 holds array length
7701     */
7702.LOP_NEW_ARRAY_finish:
7703    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7704    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7705    cmp     r0, #0                      @ failed?
7706    mov     r2, rINST, lsr #8           @ r2<- A+
7707    beq     common_exceptionThrown      @ yes, handle the exception
7708    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7709    and     r2, r2, #15                 @ r2<- A
7710    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7711    SET_VREG(r0, r2)                    @ vA<- r0
7712    GOTO_OPCODE(ip)                     @ jump to next instruction
7713
7714
7715/* continuation for OP_FILLED_NEW_ARRAY */
7716
7717    /*
7718     * On entry:
7719     *  r0 holds array class
7720     *  r10 holds AA or BA
7721     */
7722.LOP_FILLED_NEW_ARRAY_continue:
7723    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7724    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7725    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7726    .if     0
7727    mov     r1, r10                     @ r1<- AA (length)
7728    .else
7729    mov     r1, r10, lsr #4             @ r1<- B (length)
7730    .endif
7731    cmp     r3, #'I'                    @ array of ints?
7732    cmpne   r3, #'L'                    @ array of objects?
7733    cmpne   r3, #'['                    @ array of arrays?
7734    mov     r9, r1                      @ save length in r9
7735    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7736    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7737    cmp     r0, #0                      @ null return?
7738    beq     common_exceptionThrown      @ alloc failed, handle exception
7739
7740    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7741    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7742    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7743    subs    r9, r9, #1                  @ length--, check for neg
7744    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7745    bmi     2f                          @ was zero, bail
7746
7747    @ copy values from registers into the array
7748    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7749    .if     0
7750    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
77511:  ldr     r3, [r2], #4                @ r3<- *r2++
7752    subs    r9, r9, #1                  @ count--
7753    str     r3, [r0], #4                @ *contents++ = vX
7754    bpl     1b
7755    @ continue at 2
7756    .else
7757    cmp     r9, #4                      @ length was initially 5?
7758    and     r2, r10, #15                @ r2<- A
7759    bne     1f                          @ <= 4 args, branch
7760    GET_VREG(r3, r2)                    @ r3<- vA
7761    sub     r9, r9, #1                  @ count--
7762    str     r3, [r0, #16]               @ contents[4] = vA
77631:  and     r2, r1, #15                 @ r2<- F/E/D/C
7764    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7765    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7766    subs    r9, r9, #1                  @ count--
7767    str     r3, [r0], #4                @ *contents++ = vX
7768    bpl     1b
7769    @ continue at 2
7770    .endif
7771
77722:
7773    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7774    GOTO_OPCODE(ip)                     @ execute it
7775
7776    /*
7777     * Throw an exception indicating that we have not implemented this
7778     * mode of filled-new-array.
7779     */
7780.LOP_FILLED_NEW_ARRAY_notimpl:
7781    ldr     r0, .L_strInternalError
7782    ldr     r1, .L_strFilledNewArrayNotImpl
7783    bl      dvmThrowException
7784    b       common_exceptionThrown
7785
7786    .if     (!0)                 @ define in one or the other, not both
7787.L_strFilledNewArrayNotImpl:
7788    .word   .LstrFilledNewArrayNotImpl
7789.L_strInternalError:
7790    .word   .LstrInternalError
7791    .endif
7792
7793
7794/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7795
7796    /*
7797     * On entry:
7798     *  r0 holds array class
7799     *  r10 holds AA or BA
7800     */
7801.LOP_FILLED_NEW_ARRAY_RANGE_continue:
7802    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7803    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7804    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7805    .if     1
7806    mov     r1, r10                     @ r1<- AA (length)
7807    .else
7808    mov     r1, r10, lsr #4             @ r1<- B (length)
7809    .endif
7810    cmp     r3, #'I'                    @ array of ints?
7811    cmpne   r3, #'L'                    @ array of objects?
7812    cmpne   r3, #'['                    @ array of arrays?
7813    mov     r9, r1                      @ save length in r9
7814    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7815    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7816    cmp     r0, #0                      @ null return?
7817    beq     common_exceptionThrown      @ alloc failed, handle exception
7818
7819    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7820    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7821    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7822    subs    r9, r9, #1                  @ length--, check for neg
7823    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7824    bmi     2f                          @ was zero, bail
7825
7826    @ copy values from registers into the array
7827    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7828    .if     1
7829    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
78301:  ldr     r3, [r2], #4                @ r3<- *r2++
7831    subs    r9, r9, #1                  @ count--
7832    str     r3, [r0], #4                @ *contents++ = vX
7833    bpl     1b
7834    @ continue at 2
7835    .else
7836    cmp     r9, #4                      @ length was initially 5?
7837    and     r2, r10, #15                @ r2<- A
7838    bne     1f                          @ <= 4 args, branch
7839    GET_VREG(r3, r2)                    @ r3<- vA
7840    sub     r9, r9, #1                  @ count--
7841    str     r3, [r0, #16]               @ contents[4] = vA
78421:  and     r2, r1, #15                 @ r2<- F/E/D/C
7843    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7844    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7845    subs    r9, r9, #1                  @ count--
7846    str     r3, [r0], #4                @ *contents++ = vX
7847    bpl     1b
7848    @ continue at 2
7849    .endif
7850
78512:
7852    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7853    GOTO_OPCODE(ip)                     @ execute it
7854
7855    /*
7856     * Throw an exception indicating that we have not implemented this
7857     * mode of filled-new-array.
7858     */
7859.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
7860    ldr     r0, .L_strInternalError
7861    ldr     r1, .L_strFilledNewArrayNotImpl
7862    bl      dvmThrowException
7863    b       common_exceptionThrown
7864
7865    .if     (!1)                 @ define in one or the other, not both
7866.L_strFilledNewArrayNotImpl:
7867    .word   .LstrFilledNewArrayNotImpl
7868.L_strInternalError:
7869    .word   .LstrInternalError
7870    .endif
7871
7872
7873/* continuation for OP_CMPL_FLOAT */
7874.LOP_CMPL_FLOAT_finish:
7875    SET_VREG(r0, r9)                    @ vAA<- r0
7876    GOTO_OPCODE(ip)                     @ jump to next instruction
7877
7878
7879/* continuation for OP_CMPG_FLOAT */
7880.LOP_CMPG_FLOAT_finish:
7881    SET_VREG(r0, r9)                    @ vAA<- r0
7882    GOTO_OPCODE(ip)                     @ jump to next instruction
7883
7884
7885/* continuation for OP_CMPL_DOUBLE */
7886.LOP_CMPL_DOUBLE_finish:
7887    SET_VREG(r0, r9)                    @ vAA<- r0
7888    GOTO_OPCODE(ip)                     @ jump to next instruction
7889
7890
7891/* continuation for OP_CMPG_DOUBLE */
7892.LOP_CMPG_DOUBLE_finish:
7893    SET_VREG(r0, r9)                    @ vAA<- r0
7894    GOTO_OPCODE(ip)                     @ jump to next instruction
7895
7896
7897/* continuation for OP_CMP_LONG */
7898
7899.LOP_CMP_LONG_less:
7900    mvn     r1, #0                      @ r1<- -1
7901    @ Want to cond code the next mov so we can avoid branch, but don't see it;
7902    @ instead, we just replicate the tail end.
7903    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7904    SET_VREG(r1, r9)                    @ vAA<- r1
7905    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7906    GOTO_OPCODE(ip)                     @ jump to next instruction
7907
7908.LOP_CMP_LONG_greater:
7909    mov     r1, #1                      @ r1<- 1
7910    @ fall through to _finish
7911
7912.LOP_CMP_LONG_finish:
7913    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7914    SET_VREG(r1, r9)                    @ vAA<- r1
7915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7916    GOTO_OPCODE(ip)                     @ jump to next instruction
7917
7918
7919/* continuation for OP_AGET_WIDE */
7920
7921.LOP_AGET_WIDE_finish:
7922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7923    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
7924    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7925    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7926    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
7927    GOTO_OPCODE(ip)                     @ jump to next instruction
7928
7929
7930/* continuation for OP_APUT_WIDE */
7931
7932.LOP_APUT_WIDE_finish:
7933    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7934    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
7935    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7936    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
7937    GOTO_OPCODE(ip)                     @ jump to next instruction
7938
7939
7940/* continuation for OP_APUT_OBJECT */
7941    /*
7942     * On entry:
7943     *  r1 = vBB (arrayObj)
7944     *  r9 = vAA (obj)
7945     *  r10 = offset into array (vBB + vCC * width)
7946     */
7947.LOP_APUT_OBJECT_finish:
7948    cmp     r9, #0                      @ storing null reference?
7949    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
7950    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7951    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
7952    bl      dvmCanPutArrayElement       @ test object type vs. array type
7953    cmp     r0, #0                      @ okay?
7954    beq     common_errArrayStore        @ no
7955.LOP_APUT_OBJECT_skip_check:
7956    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7958    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
7959    GOTO_OPCODE(ip)                     @ jump to next instruction
7960
7961
7962/* continuation for OP_IGET */
7963
7964    /*
7965     * Currently:
7966     *  r0 holds resolved field
7967     *  r9 holds object
7968     */
7969.LOP_IGET_finish:
7970    @bl      common_squeak0
7971    cmp     r9, #0                      @ check object for null
7972    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
7973    beq     common_errNullObject        @ object was null
7974    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
7975    mov     r2, rINST, lsr #8           @ r2<- A+
7976    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7977    and     r2, r2, #15                 @ r2<- A
7978    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7979    SET_VREG(r0, r2)                    @ fp[A]<- r0
7980    GOTO_OPCODE(ip)                     @ jump to next instruction
7981
7982
7983/* continuation for OP_IGET_WIDE */
7984
7985    /*
7986     * Currently:
7987     *  r0 holds resolved field
7988     *  r9 holds object
7989     */
7990.LOP_IGET_WIDE_finish:
7991    cmp     r9, #0                      @ check object for null
7992    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
7993    beq     common_errNullObject        @ object was null
7994    mov     r2, rINST, lsr #8           @ r2<- A+
7995    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
7996    and     r2, r2, #15                 @ r2<- A
7997    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7998    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7999    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8000    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8001    GOTO_OPCODE(ip)                     @ jump to next instruction
8002
8003
8004/* continuation for OP_IGET_OBJECT */
8005
8006    /*
8007     * Currently:
8008     *  r0 holds resolved field
8009     *  r9 holds object
8010     */
8011.LOP_IGET_OBJECT_finish:
8012    @bl      common_squeak0
8013    cmp     r9, #0                      @ check object for null
8014    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8015    beq     common_errNullObject        @ object was null
8016    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8017    mov     r2, rINST, lsr #8           @ r2<- A+
8018    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8019    and     r2, r2, #15                 @ r2<- A
8020    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8021    SET_VREG(r0, r2)                    @ fp[A]<- r0
8022    GOTO_OPCODE(ip)                     @ jump to next instruction
8023
8024
8025/* continuation for OP_IGET_BOOLEAN */
8026
8027    /*
8028     * Currently:
8029     *  r0 holds resolved field
8030     *  r9 holds object
8031     */
8032.LOP_IGET_BOOLEAN_finish:
8033    @bl      common_squeak1
8034    cmp     r9, #0                      @ check object for null
8035    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8036    beq     common_errNullObject        @ object was null
8037    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8038    mov     r2, rINST, lsr #8           @ r2<- A+
8039    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8040    and     r2, r2, #15                 @ r2<- A
8041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8042    SET_VREG(r0, r2)                    @ fp[A]<- r0
8043    GOTO_OPCODE(ip)                     @ jump to next instruction
8044
8045
8046/* continuation for OP_IGET_BYTE */
8047
8048    /*
8049     * Currently:
8050     *  r0 holds resolved field
8051     *  r9 holds object
8052     */
8053.LOP_IGET_BYTE_finish:
8054    @bl      common_squeak2
8055    cmp     r9, #0                      @ check object for null
8056    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8057    beq     common_errNullObject        @ object was null
8058    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8059    mov     r2, rINST, lsr #8           @ r2<- A+
8060    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8061    and     r2, r2, #15                 @ r2<- A
8062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8063    SET_VREG(r0, r2)                    @ fp[A]<- r0
8064    GOTO_OPCODE(ip)                     @ jump to next instruction
8065
8066
8067/* continuation for OP_IGET_CHAR */
8068
8069    /*
8070     * Currently:
8071     *  r0 holds resolved field
8072     *  r9 holds object
8073     */
8074.LOP_IGET_CHAR_finish:
8075    @bl      common_squeak3
8076    cmp     r9, #0                      @ check object for null
8077    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8078    beq     common_errNullObject        @ object was null
8079    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8080    mov     r2, rINST, lsr #8           @ r2<- A+
8081    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8082    and     r2, r2, #15                 @ r2<- A
8083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8084    SET_VREG(r0, r2)                    @ fp[A]<- r0
8085    GOTO_OPCODE(ip)                     @ jump to next instruction
8086
8087
8088/* continuation for OP_IGET_SHORT */
8089
8090    /*
8091     * Currently:
8092     *  r0 holds resolved field
8093     *  r9 holds object
8094     */
8095.LOP_IGET_SHORT_finish:
8096    @bl      common_squeak4
8097    cmp     r9, #0                      @ check object for null
8098    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8099    beq     common_errNullObject        @ object was null
8100    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8101    mov     r2, rINST, lsr #8           @ r2<- A+
8102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8103    and     r2, r2, #15                 @ r2<- A
8104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8105    SET_VREG(r0, r2)                    @ fp[A]<- r0
8106    GOTO_OPCODE(ip)                     @ jump to next instruction
8107
8108
8109/* continuation for OP_IPUT */
8110
8111    /*
8112     * Currently:
8113     *  r0 holds resolved field
8114     *  r9 holds object
8115     */
8116.LOP_IPUT_finish:
8117    @bl      common_squeak0
8118    mov     r1, rINST, lsr #8           @ r1<- A+
8119    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8120    and     r1, r1, #15                 @ r1<- A
8121    cmp     r9, #0                      @ check object for null
8122    GET_VREG(r0, r1)                    @ r0<- fp[A]
8123    beq     common_errNullObject        @ object was null
8124    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8125    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8126    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8127    GOTO_OPCODE(ip)                     @ jump to next instruction
8128
8129
8130/* continuation for OP_IPUT_WIDE */
8131
8132    /*
8133     * Currently:
8134     *  r0 holds resolved field
8135     *  r9 holds object
8136     */
8137.LOP_IPUT_WIDE_finish:
8138    mov     r2, rINST, lsr #8           @ r2<- A+
8139    cmp     r9, #0                      @ check object for null
8140    and     r2, r2, #15                 @ r2<- A
8141    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8142    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8143    beq     common_errNullObject        @ object was null
8144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8145    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8147    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8148    GOTO_OPCODE(ip)                     @ jump to next instruction
8149
8150
8151/* continuation for OP_IPUT_OBJECT */
8152
8153    /*
8154     * Currently:
8155     *  r0 holds resolved field
8156     *  r9 holds object
8157     */
8158.LOP_IPUT_OBJECT_finish:
8159    @bl      common_squeak0
8160    mov     r1, rINST, lsr #8           @ r1<- A+
8161    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8162    and     r1, r1, #15                 @ r1<- A
8163    cmp     r9, #0                      @ check object for null
8164    GET_VREG(r0, r1)                    @ r0<- fp[A]
8165    beq     common_errNullObject        @ object was null
8166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8168    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8169    GOTO_OPCODE(ip)                     @ jump to next instruction
8170
8171
8172/* continuation for OP_IPUT_BOOLEAN */
8173
8174    /*
8175     * Currently:
8176     *  r0 holds resolved field
8177     *  r9 holds object
8178     */
8179.LOP_IPUT_BOOLEAN_finish:
8180    @bl      common_squeak1
8181    mov     r1, rINST, lsr #8           @ r1<- A+
8182    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8183    and     r1, r1, #15                 @ r1<- A
8184    cmp     r9, #0                      @ check object for null
8185    GET_VREG(r0, r1)                    @ r0<- fp[A]
8186    beq     common_errNullObject        @ object was null
8187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8189    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8190    GOTO_OPCODE(ip)                     @ jump to next instruction
8191
8192
8193/* continuation for OP_IPUT_BYTE */
8194
8195    /*
8196     * Currently:
8197     *  r0 holds resolved field
8198     *  r9 holds object
8199     */
8200.LOP_IPUT_BYTE_finish:
8201    @bl      common_squeak2
8202    mov     r1, rINST, lsr #8           @ r1<- A+
8203    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8204    and     r1, r1, #15                 @ r1<- A
8205    cmp     r9, #0                      @ check object for null
8206    GET_VREG(r0, r1)                    @ r0<- fp[A]
8207    beq     common_errNullObject        @ object was null
8208    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8210    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8211    GOTO_OPCODE(ip)                     @ jump to next instruction
8212
8213
8214/* continuation for OP_IPUT_CHAR */
8215
8216    /*
8217     * Currently:
8218     *  r0 holds resolved field
8219     *  r9 holds object
8220     */
8221.LOP_IPUT_CHAR_finish:
8222    @bl      common_squeak3
8223    mov     r1, rINST, lsr #8           @ r1<- A+
8224    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8225    and     r1, r1, #15                 @ r1<- A
8226    cmp     r9, #0                      @ check object for null
8227    GET_VREG(r0, r1)                    @ r0<- fp[A]
8228    beq     common_errNullObject        @ object was null
8229    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8231    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8232    GOTO_OPCODE(ip)                     @ jump to next instruction
8233
8234
8235/* continuation for OP_IPUT_SHORT */
8236
8237    /*
8238     * Currently:
8239     *  r0 holds resolved field
8240     *  r9 holds object
8241     */
8242.LOP_IPUT_SHORT_finish:
8243    @bl      common_squeak4
8244    mov     r1, rINST, lsr #8           @ r1<- A+
8245    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8246    and     r1, r1, #15                 @ r1<- A
8247    cmp     r9, #0                      @ check object for null
8248    GET_VREG(r0, r1)                    @ r0<- fp[A]
8249    beq     common_errNullObject        @ object was null
8250    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8251    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8252    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8253    GOTO_OPCODE(ip)                     @ jump to next instruction
8254
8255
8256/* continuation for OP_SGET */
8257
8258    /*
8259     * Continuation if the field has not yet been resolved.
8260     *  r1: BBBB field ref
8261     */
8262.LOP_SGET_resolve:
8263    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8264    EXPORT_PC()                         @ resolve() could throw, so export now
8265    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8266    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8267    cmp     r0, #0                      @ success?
8268    bne     .LOP_SGET_finish          @ yes, finish
8269    b       common_exceptionThrown      @ no, handle exception
8270
8271
8272/* continuation for OP_SGET_WIDE */
8273
8274    /*
8275     * Continuation if the field has not yet been resolved.
8276     *  r1: BBBB field ref
8277     */
8278.LOP_SGET_WIDE_resolve:
8279    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8280    EXPORT_PC()                         @ resolve() could throw, so export now
8281    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8282    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8283    cmp     r0, #0                      @ success?
8284    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8285    b       common_exceptionThrown      @ no, handle exception
8286
8287
8288/* continuation for OP_SGET_OBJECT */
8289
8290    /*
8291     * Continuation if the field has not yet been resolved.
8292     *  r1: BBBB field ref
8293     */
8294.LOP_SGET_OBJECT_resolve:
8295    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8296    EXPORT_PC()                         @ resolve() could throw, so export now
8297    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8298    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8299    cmp     r0, #0                      @ success?
8300    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8301    b       common_exceptionThrown      @ no, handle exception
8302
8303
8304/* continuation for OP_SGET_BOOLEAN */
8305
8306    /*
8307     * Continuation if the field has not yet been resolved.
8308     *  r1: BBBB field ref
8309     */
8310.LOP_SGET_BOOLEAN_resolve:
8311    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8312    EXPORT_PC()                         @ resolve() could throw, so export now
8313    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8314    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8315    cmp     r0, #0                      @ success?
8316    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8317    b       common_exceptionThrown      @ no, handle exception
8318
8319
8320/* continuation for OP_SGET_BYTE */
8321
8322    /*
8323     * Continuation if the field has not yet been resolved.
8324     *  r1: BBBB field ref
8325     */
8326.LOP_SGET_BYTE_resolve:
8327    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8328    EXPORT_PC()                         @ resolve() could throw, so export now
8329    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8330    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8331    cmp     r0, #0                      @ success?
8332    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8333    b       common_exceptionThrown      @ no, handle exception
8334
8335
8336/* continuation for OP_SGET_CHAR */
8337
8338    /*
8339     * Continuation if the field has not yet been resolved.
8340     *  r1: BBBB field ref
8341     */
8342.LOP_SGET_CHAR_resolve:
8343    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8344    EXPORT_PC()                         @ resolve() could throw, so export now
8345    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8346    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8347    cmp     r0, #0                      @ success?
8348    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8349    b       common_exceptionThrown      @ no, handle exception
8350
8351
8352/* continuation for OP_SGET_SHORT */
8353
8354    /*
8355     * Continuation if the field has not yet been resolved.
8356     *  r1: BBBB field ref
8357     */
8358.LOP_SGET_SHORT_resolve:
8359    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8360    EXPORT_PC()                         @ resolve() could throw, so export now
8361    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8362    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8363    cmp     r0, #0                      @ success?
8364    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8365    b       common_exceptionThrown      @ no, handle exception
8366
8367
8368/* continuation for OP_SPUT */
8369
8370    /*
8371     * Continuation if the field has not yet been resolved.
8372     *  r1: BBBB field ref
8373     */
8374.LOP_SPUT_resolve:
8375    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8376    EXPORT_PC()                         @ resolve() could throw, so export now
8377    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8378    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8379    cmp     r0, #0                      @ success?
8380    bne     .LOP_SPUT_finish          @ yes, finish
8381    b       common_exceptionThrown      @ no, handle exception
8382
8383
8384/* continuation for OP_SPUT_WIDE */
8385
8386    /*
8387     * Continuation if the field has not yet been resolved.
8388     *  r1: BBBB field ref
8389     *  r9: &fp[AA]
8390     */
8391.LOP_SPUT_WIDE_resolve:
8392    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8393    EXPORT_PC()                         @ resolve() could throw, so export now
8394    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8395    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8396    cmp     r0, #0                      @ success?
8397    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8398    b       common_exceptionThrown      @ no, handle exception
8399
8400
8401/* continuation for OP_SPUT_OBJECT */
8402
8403    /*
8404     * Continuation if the field has not yet been resolved.
8405     *  r1: BBBB field ref
8406     */
8407.LOP_SPUT_OBJECT_resolve:
8408    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8409    EXPORT_PC()                         @ resolve() could throw, so export now
8410    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8411    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8412    cmp     r0, #0                      @ success?
8413    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8414    b       common_exceptionThrown      @ no, handle exception
8415
8416
8417/* continuation for OP_SPUT_BOOLEAN */
8418
8419    /*
8420     * Continuation if the field has not yet been resolved.
8421     *  r1: BBBB field ref
8422     */
8423.LOP_SPUT_BOOLEAN_resolve:
8424    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8425    EXPORT_PC()                         @ resolve() could throw, so export now
8426    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8427    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8428    cmp     r0, #0                      @ success?
8429    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8430    b       common_exceptionThrown      @ no, handle exception
8431
8432
8433/* continuation for OP_SPUT_BYTE */
8434
8435    /*
8436     * Continuation if the field has not yet been resolved.
8437     *  r1: BBBB field ref
8438     */
8439.LOP_SPUT_BYTE_resolve:
8440    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8441    EXPORT_PC()                         @ resolve() could throw, so export now
8442    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8443    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8444    cmp     r0, #0                      @ success?
8445    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8446    b       common_exceptionThrown      @ no, handle exception
8447
8448
8449/* continuation for OP_SPUT_CHAR */
8450
8451    /*
8452     * Continuation if the field has not yet been resolved.
8453     *  r1: BBBB field ref
8454     */
8455.LOP_SPUT_CHAR_resolve:
8456    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8457    EXPORT_PC()                         @ resolve() could throw, so export now
8458    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8459    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8460    cmp     r0, #0                      @ success?
8461    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8462    b       common_exceptionThrown      @ no, handle exception
8463
8464
8465/* continuation for OP_SPUT_SHORT */
8466
8467    /*
8468     * Continuation if the field has not yet been resolved.
8469     *  r1: BBBB field ref
8470     */
8471.LOP_SPUT_SHORT_resolve:
8472    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8473    EXPORT_PC()                         @ resolve() could throw, so export now
8474    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8475    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8476    cmp     r0, #0                      @ success?
8477    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8478    b       common_exceptionThrown      @ no, handle exception
8479
8480
8481/* continuation for OP_INVOKE_VIRTUAL */
8482
8483    /*
8484     * At this point:
8485     *  r0 = resolved base method
8486     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8487     */
8488.LOP_INVOKE_VIRTUAL_continue:
8489    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8490    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8491    cmp     r1, #0                      @ is "this" null?
8492    beq     common_errNullObject        @ null "this", throw exception
8493    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8494    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8495    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8496    bl      common_invokeMethodNoRange @ continue on
8497
8498
8499/* continuation for OP_INVOKE_SUPER */
8500
8501    /*
8502     * At this point:
8503     *  r0 = resolved base method
8504     *  r9 = method->clazz
8505     */
8506.LOP_INVOKE_SUPER_continue:
8507    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8508    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8509    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8510    EXPORT_PC()                         @ must export for invoke
8511    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8512    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8513    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8514    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8515    bl      common_invokeMethodNoRange @ continue on
8516
8517.LOP_INVOKE_SUPER_resolve:
8518    mov     r0, r9                      @ r0<- method->clazz
8519    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8520    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8521    cmp     r0, #0                      @ got null?
8522    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8523    b       common_exceptionThrown      @ yes, handle exception
8524
8525    /*
8526     * Throw a NoSuchMethodError with the method name as the message.
8527     *  r0 = resolved base method
8528     */
8529.LOP_INVOKE_SUPER_nsm:
8530    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8531    b       common_errNoSuchMethod
8532
8533
8534/* continuation for OP_INVOKE_DIRECT */
8535
8536    /*
8537     * On entry:
8538     *  r1 = reference (BBBB or CCCC)
8539     *  r10 = "this" register
8540     */
8541.LOP_INVOKE_DIRECT_resolve:
8542    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8543    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8544    mov     r2, #METHOD_DIRECT          @ resolver method type
8545    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8546    cmp     r0, #0                      @ got null?
8547    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8548    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8549    b       common_exceptionThrown      @ yes, handle exception
8550
8551
8552/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8553
8554    /*
8555     * At this point:
8556     *  r0 = resolved base method
8557     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8558     */
8559.LOP_INVOKE_VIRTUAL_RANGE_continue:
8560    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8561    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8562    cmp     r1, #0                      @ is "this" null?
8563    beq     common_errNullObject        @ null "this", throw exception
8564    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8565    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8566    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8567    bl      common_invokeMethodRange @ continue on
8568
8569
8570/* continuation for OP_INVOKE_SUPER_RANGE */
8571
8572    /*
8573     * At this point:
8574     *  r0 = resolved base method
8575     *  r9 = method->clazz
8576     */
8577.LOP_INVOKE_SUPER_RANGE_continue:
8578    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8579    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8580    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8581    EXPORT_PC()                         @ must export for invoke
8582    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8583    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8584    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8585    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8586    bl      common_invokeMethodRange @ continue on
8587
8588.LOP_INVOKE_SUPER_RANGE_resolve:
8589    mov     r0, r9                      @ r0<- method->clazz
8590    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8591    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8592    cmp     r0, #0                      @ got null?
8593    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8594    b       common_exceptionThrown      @ yes, handle exception
8595
8596    /*
8597     * Throw a NoSuchMethodError with the method name as the message.
8598     *  r0 = resolved base method
8599     */
8600.LOP_INVOKE_SUPER_RANGE_nsm:
8601    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8602    b       common_errNoSuchMethod
8603
8604
8605/* continuation for OP_INVOKE_DIRECT_RANGE */
8606
8607    /*
8608     * On entry:
8609     *  r1 = reference (BBBB or CCCC)
8610     *  r10 = "this" register
8611     */
8612.LOP_INVOKE_DIRECT_RANGE_resolve:
8613    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8614    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8615    mov     r2, #METHOD_DIRECT          @ resolver method type
8616    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8617    cmp     r0, #0                      @ got null?
8618    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8619    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8620    b       common_exceptionThrown      @ yes, handle exception
8621
8622
8623/* continuation for OP_FLOAT_TO_LONG */
8624/*
8625 * Convert the float in r0 to a long in r0/r1.
8626 *
8627 * We have to clip values to long min/max per the specification.  The
8628 * expected common case is a "reasonable" value that converts directly
8629 * to modest integer.  The EABI convert function isn't doing this for us.
8630 */
8631f2l_doconv:
8632    stmfd   sp!, {r4, lr}
8633    mov     r1, #0x5f000000             @ (float)maxlong
8634    mov     r4, r0
8635    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8636    cmp     r0, #0                      @ nonzero == yes
8637    mvnne   r0, #0                      @ return maxlong (7fffffff)
8638    mvnne   r1, #0x80000000
8639    ldmnefd sp!, {r4, pc}
8640
8641    mov     r0, r4                      @ recover arg
8642    mov     r1, #0xdf000000             @ (float)minlong
8643    bl      __aeabi_fcmple              @ is arg <= minlong?
8644    cmp     r0, #0                      @ nonzero == yes
8645    movne   r0, #0                      @ return minlong (80000000)
8646    movne   r1, #0x80000000
8647    ldmnefd sp!, {r4, pc}
8648
8649    mov     r0, r4                      @ recover arg
8650    mov     r1, r4
8651    bl      __aeabi_fcmpeq              @ is arg == self?
8652    cmp     r0, #0                      @ zero == no
8653    moveq   r1, #0                      @ return zero for NaN
8654    ldmeqfd sp!, {r4, pc}
8655
8656    mov     r0, r4                      @ recover arg
8657    bl      __aeabi_f2lz                @ convert float to long
8658    ldmfd   sp!, {r4, pc}
8659
8660
8661/* continuation for OP_DOUBLE_TO_LONG */
8662/*
8663 * Convert the double in r0/r1 to a long in r0/r1.
8664 *
8665 * We have to clip values to long min/max per the specification.  The
8666 * expected common case is a "reasonable" value that converts directly
8667 * to modest integer.  The EABI convert function isn't doing this for us.
8668 */
8669d2l_doconv:
8670    stmfd   sp!, {r4, r5, lr}           @ save regs
8671    ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
8672    sub     sp, sp, #4                  @ align for EABI
8673    mov     r2, #0                      @ (double)maxlong, lo
8674    mov     r4, r0                      @ save r0
8675    mov     r5, r1                      @  and r1
8676    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8677    cmp     r0, #0                      @ nonzero == yes
8678    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8679    mvnne   r1, #0x80000000
8680    bne     1f
8681
8682    mov     r0, r4                      @ recover arg
8683    mov     r1, r5
8684    ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
8685    mov     r2, #0                      @ (double)minlong, lo
8686    bl      __aeabi_dcmple              @ is arg <= minlong?
8687    cmp     r0, #0                      @ nonzero == yes
8688    movne   r0, #0                      @ return minlong (8000000000000000)
8689    movne   r1, #0x80000000
8690    bne     1f
8691
8692    mov     r0, r4                      @ recover arg
8693    mov     r1, r5
8694    mov     r2, r4                      @ compare against self
8695    mov     r3, r5
8696    bl      __aeabi_dcmpeq              @ is arg == self?
8697    cmp     r0, #0                      @ zero == no
8698    moveq   r1, #0                      @ return zero for NaN
8699    beq     1f
8700
8701    mov     r0, r4                      @ recover arg
8702    mov     r1, r5
8703    bl      __aeabi_d2lz                @ convert double to long
8704
87051:
8706    add     sp, sp, #4
8707    ldmfd   sp!, {r4, r5, pc}
8708
8709.LOP_DOUBLE_TO_LONG_max:
8710    .word   0x43e00000                  @ maxlong, as a double (high word)
8711.LOP_DOUBLE_TO_LONG_min:
8712    .word   0xc3e00000                  @ minlong, as a double (high word)
8713
8714
8715/* continuation for OP_MUL_LONG */
8716
8717.LOP_MUL_LONG_finish:
8718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8719    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8720    GOTO_OPCODE(ip)                     @ jump to next instruction
8721
8722
8723/* continuation for OP_SHL_LONG */
8724
8725.LOP_SHL_LONG_finish:
8726    mov     r0, r0, asl r2              @  r0<- r0 << r2
8727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8728    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8729    GOTO_OPCODE(ip)                     @ jump to next instruction
8730
8731
8732/* continuation for OP_SHR_LONG */
8733
8734.LOP_SHR_LONG_finish:
8735    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8737    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8738    GOTO_OPCODE(ip)                     @ jump to next instruction
8739
8740
8741/* continuation for OP_USHR_LONG */
8742
8743.LOP_USHR_LONG_finish:
8744    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8746    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8747    GOTO_OPCODE(ip)                     @ jump to next instruction
8748
8749
8750/* continuation for OP_SHL_LONG_2ADDR */
8751
8752.LOP_SHL_LONG_2ADDR_finish:
8753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8754    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8755    GOTO_OPCODE(ip)                     @ jump to next instruction
8756
8757
8758/* continuation for OP_SHR_LONG_2ADDR */
8759
8760.LOP_SHR_LONG_2ADDR_finish:
8761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8762    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8763    GOTO_OPCODE(ip)                     @ jump to next instruction
8764
8765
8766/* continuation for OP_USHR_LONG_2ADDR */
8767
8768.LOP_USHR_LONG_2ADDR_finish:
8769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8770    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8771    GOTO_OPCODE(ip)                     @ jump to next instruction
8772
8773
8774/* continuation for OP_EXECUTE_INLINE */
8775
8776    /*
8777     * Extract args, call function.
8778     *  r0 = #of args (0-4)
8779     *  r10 = call index
8780     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8781     *
8782     * Other ideas:
8783     * - Use a jump table from the main piece to jump directly into the
8784     *   AND/LDR pairs.  Costs a data load, saves a branch.
8785     * - Have five separate pieces that do the loading, so we can work the
8786     *   interleave a little better.  Increases code size.
8787     */
8788.LOP_EXECUTE_INLINE_continue:
8789    rsb     r0, r0, #4                  @ r0<- 4-r0
8790    FETCH(r9, 2)                        @ r9<- FEDC
8791    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8792    bl      common_abort                @ (skipped due to ARM prefetch)
87934:  and     ip, r9, #0xf000             @ isolate F
8794    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
87953:  and     ip, r9, #0x0f00             @ isolate E
8796    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
87972:  and     ip, r9, #0x00f0             @ isolate D
8798    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
87991:  and     ip, r9, #0x000f             @ isolate C
8800    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
88010:
8802    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8803    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8804    @ (not reached)
8805
8806.LOP_EXECUTE_INLINE_table:
8807    .word   gDvmInlineOpsTable
8808
8809
8810    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8811    .global dvmAsmSisterEnd
8812dvmAsmSisterEnd:
8813
8814/* File: armv5te/footer.S */
8815/*
8816 * ===========================================================================
8817 *  Common subroutines and data
8818 * ===========================================================================
8819 */
8820
8821    .text
8822    .align  2
8823
8824/*
8825 * Common code when a backward branch is taken.
8826 *
8827 * On entry:
8828 *  r9 is PC adjustment *in bytes*
8829 */
8830common_backwardBranch:
8831    mov     r0, #kInterpEntryInstr
8832    bl      common_periodicChecks
8833    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
8834    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8835    GOTO_OPCODE(ip)                     @ jump to next instruction
8836
8837
8838/*
8839 * Need to see if the thread needs to be suspended or debugger/profiler
8840 * activity has begun.
8841 *
8842 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
8843 * have to do the second ldr.
8844 *
8845 * TODO: reduce this so we're just checking a single location.
8846 *
8847 * On entry:
8848 *  r0 is reentry type, e.g. kInterpEntryInstr
8849 *  r9 is trampoline PC adjustment *in bytes*
8850 */
8851common_periodicChecks:
8852    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
8853
8854#if defined(WITH_DEBUGGER)
8855    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
8856#endif
8857#if defined(WITH_PROFILER)
8858    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
8859#endif
8860
8861    ldr     r3, [r3]                    @ r3<- suspendCount (int)
8862
8863#if defined(WITH_DEBUGGER)
8864    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
8865#endif
8866#if defined (WITH_PROFILER)
8867    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
8868#endif
8869
8870    cmp     r3, #0                      @ suspend pending?
8871    bne     2f                          @ yes, do full suspension check
8872
8873#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
8874# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
8875    orrs    r1, r1, r2                  @ r1<- r1 | r2
8876    cmp     r1, #0                      @ debugger attached or profiler started?
8877# elif defined(WITH_DEBUGGER)
8878    cmp     r1, #0                      @ debugger attached?
8879# elif defined(WITH_PROFILER)
8880    cmp     r2, #0                      @ profiler started?
8881# endif
8882    bne     3f                          @ debugger/profiler, switch interp
8883#endif
8884
8885    bx      lr                          @ nothing to do, return
8886
88872:  @ check suspend
8888    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
8889    EXPORT_PC()                         @ need for precise GC
8890    b       dvmCheckSuspendPending      @ suspend if necessary, then return
8891
88923:  @ debugger/profiler enabled, bail out
8893    add     rPC, rPC, r9                @ update rPC
8894    str     r0, [rGLUE, #offGlue_entryPoint]
8895    mov     r1, #1                      @ "want switch" = true
8896    b       common_gotoBail
8897
8898
8899/*
8900 * The equivalent of "goto bail", this calls through the "bail handler".
8901 *
8902 * State registers will be saved to the "glue" area before bailing.
8903 *
8904 * On entry:
8905 *  r1 is "bool changeInterp", indicating if we want to switch to the
8906 *     other interpreter or just bail all the way out
8907 */
8908common_gotoBail:
8909    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
8910    mov     r0, rGLUE                   @ r0<- glue ptr
8911    b       dvmMterpStdBail             @ call(glue, changeInterp)
8912
8913    @add     r1, r1, #1                  @ using (boolean+1)
8914    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
8915    @bl      _longjmp                    @ does not return
8916    @bl      common_abort
8917
8918
8919/*
8920 * Common code for method invocation with range.
8921 *
8922 * On entry:
8923 *  r0 is "Method* methodToCall", the method we're trying to call
8924 */
8925common_invokeMethodRange:
8926.LinvokeNewRange:
8927    @ prepare to copy args to "outs" area of current frame
8928    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
8929    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
8930    beq     .LinvokeArgsDone            @ if no args, skip the rest
8931    FETCH(r1, 2)                        @ r1<- CCCC
8932
8933    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
8934    @ (very few methods have > 10 args; could unroll for common cases)
8935    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
8936    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
8937    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
89381:  ldr     r1, [r3], #4                @ val = *fp++
8939    subs    r2, r2, #1                  @ count--
8940    str     r1, [r10], #4               @ *outs++ = val
8941    bne     1b                          @ ...while count != 0
8942    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
8943    b       .LinvokeArgsDone
8944
8945/*
8946 * Common code for method invocation without range.
8947 *
8948 * On entry:
8949 *  r0 is "Method* methodToCall", the method we're trying to call
8950 */
8951common_invokeMethodNoRange:
8952.LinvokeNewNoRange:
8953    @ prepare to copy args to "outs" area of current frame
8954    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
8955    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
8956    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
8957    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
8958    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
8959    beq     .LinvokeArgsDone
8960
8961    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
8962.LinvokeNonRange:
8963    rsb     r2, r2, #5                  @ r2<- 5-r2
8964    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
8965    bl      common_abort                @ (skipped due to ARM prefetch)
89665:  and     ip, rINST, #0x0f00          @ isolate A
8967    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
8968    mov     r0, r0                      @ nop
8969    str     r2, [r10, #-4]!             @ *--outs = vA
89704:  and     ip, r1, #0xf000             @ isolate G
8971    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
8972    mov     r0, r0                      @ nop
8973    str     r2, [r10, #-4]!             @ *--outs = vG
89743:  and     ip, r1, #0x0f00             @ isolate F
8975    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
8976    mov     r0, r0                      @ nop
8977    str     r2, [r10, #-4]!             @ *--outs = vF
89782:  and     ip, r1, #0x00f0             @ isolate E
8979    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
8980    mov     r0, r0                      @ nop
8981    str     r2, [r10, #-4]!             @ *--outs = vE
89821:  and     ip, r1, #0x000f             @ isolate D
8983    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
8984    mov     r0, r0                      @ nop
8985    str     r2, [r10, #-4]!             @ *--outs = vD
89860:  @ fall through to .LinvokeArgsDone
8987
8988.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
8989    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
8990    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
8991    @ find space for the new stack frame, check for overflow
8992    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
8993    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
8994    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
8995@    bl      common_dumpRegs
8996    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
8997    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
8998    cmp     r3, r9                      @ bottom < interpStackEnd?
8999    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9000    blt     .LstackOverflow             @ yes, this frame will overflow stack
9001
9002    @ set up newSaveArea
9003#ifdef EASY_GDB
9004    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9005    str     ip, [r10, #offStackSaveArea_prevSave]
9006#endif
9007    str     rFP, [r10, #offStackSaveArea_prevFrame]
9008    str     rPC, [r10, #offStackSaveArea_savedPc]
9009    str     r0, [r10, #offStackSaveArea_method]
9010    tst     r3, #ACC_NATIVE
9011    bne     .LinvokeNative
9012
9013    /*
9014    stmfd   sp!, {r0-r3}
9015    bl      common_printNewline
9016    mov     r0, rFP
9017    mov     r1, #0
9018    bl      dvmDumpFp
9019    ldmfd   sp!, {r0-r3}
9020    stmfd   sp!, {r0-r3}
9021    mov     r0, r1
9022    mov     r1, r10
9023    bl      dvmDumpFp
9024    bl      common_printNewline
9025    ldmfd   sp!, {r0-r3}
9026    */
9027
9028    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9029    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9030    mov     rPC, r2                         @ publish new rPC
9031    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9032
9033    @ Update "glue" values for the new method
9034    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9035    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9036    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9037    mov     rFP, r1                         @ fp = newFp
9038    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9039    mov     rINST, r9                       @ publish new rINST
9040    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9041    GOTO_OPCODE(ip)                         @ jump to next instruction
9042
9043.LinvokeNative:
9044    @ Prep for the native call
9045    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9046    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9047    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
9048    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9049    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
9050    mov     r9, r3                      @ r9<- glue->self (preserve)
9051
9052    mov     r2, r0                      @ r2<- methodToCall
9053    mov     r0, r1                      @ r0<- newFp (points to args)
9054    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9055
9056#ifdef ASSIST_DEBUGGER
9057    /* insert fake function header to help gdb find the stack frame */
9058    b       .Lskip
9059    .type   dalvik_mterp, %function
9060dalvik_mterp:
9061    .fnstart
9062    MTERP_ENTRY1
9063    MTERP_ENTRY2
9064.Lskip:
9065#endif
9066
9067    @mov     lr, pc                      @ set return addr
9068    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9069    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9070
9071    @ native return; r9=self, r10=newSaveArea
9072    @ equivalent to dvmPopJniLocals
9073    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
9074    ldr     r1, [r9, #offThread_exception] @ check for exception
9075    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9076    cmp     r1, #0                      @ null?
9077    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
9078    bne     common_exceptionThrown      @ no, handle exception
9079
9080    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9082    GOTO_OPCODE(ip)                     @ jump to next instruction
9083
9084.LstackOverflow:
9085    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9086    bl      dvmHandleStackOverflow
9087    b       common_exceptionThrown
9088#ifdef ASSIST_DEBUGGER
9089    .fnend
9090#endif
9091
9092
9093    /*
9094     * Common code for method invocation, calling through "glue code".
9095     *
9096     * TODO: now that we have range and non-range invoke handlers, this
9097     *       needs to be split into two.  Maybe just create entry points
9098     *       that set r9 and jump here?
9099     *
9100     * On entry:
9101     *  r0 is "Method* methodToCall", the method we're trying to call
9102     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9103     */
9104     .if    0
9105.LinvokeOld:
9106    sub     sp, sp, #8                  @ space for args + pad
9107    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9108    mov     r2, r0                      @ A2<- methodToCall
9109    mov     r0, rGLUE                   @ A0<- glue
9110    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9111    mov     r1, r9                      @ A1<- methodCallRange
9112    mov     r3, rINST, lsr #8           @ A3<- AA
9113    str     ip, [sp, #0]                @ A4<- ip
9114    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9115    add     sp, sp, #8                  @ remove arg area
9116    b       common_resumeAfterGlueCall  @ continue to next instruction
9117    .endif
9118
9119
9120
9121/*
9122 * Common code for handling a return instruction.
9123 *
9124 * This does not return.
9125 */
9126common_returnFromMethod:
9127.LreturnNew:
9128    mov     r0, #kInterpEntryReturn
9129    mov     r9, #0
9130    bl      common_periodicChecks
9131
9132    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9133    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9134    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9135    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9136                                        @ r2<- method we're returning to
9137    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9138    cmp     r2, #0                      @ is this a break frame?
9139    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9140    mov     r1, #0                      @ "want switch" = false
9141    beq     common_gotoBail             @ break frame, bail out completely
9142
9143    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9144    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9145    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9146    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9148    mov     rPC, r9                     @ publish new rPC
9149    str     r1, [rGLUE, #offGlue_methodClassDex]
9150    GOTO_OPCODE(ip)                     @ jump to next instruction
9151
9152    /*
9153     * Return handling, calls through "glue code".
9154     */
9155     .if    0
9156.LreturnOld:
9157    SAVE_PC_FP_TO_GLUE()                @ export state
9158    mov     r0, rGLUE                   @ arg to function
9159    bl      dvmMterp_returnFromMethod
9160    b       common_resumeAfterGlueCall
9161    .endif
9162
9163
9164/*
9165 * Somebody has thrown an exception.  Handle it.
9166 *
9167 * If the exception processing code returns to us (instead of falling
9168 * out of the interpreter), continue with whatever the next instruction
9169 * now happens to be.
9170 *
9171 * This does not return.
9172 */
9173common_exceptionThrown:
9174.LexceptionNew:
9175    mov     r0, #kInterpEntryThrow
9176    mov     r9, #0
9177    bl      common_periodicChecks
9178
9179    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9180    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9181    mov     r1, r10                     @ r1<- self
9182    mov     r0, r9                      @ r0<- exception
9183    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9184    mov     r3, #0                      @ r3<- NULL
9185    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9186
9187    /* set up args and a local for "&fp" */
9188    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9189    str     rFP, [sp, #-4]!             @ *--sp = fp
9190    mov     ip, sp                      @ ip<- &fp
9191    mov     r3, #0                      @ r3<- false
9192    str     ip, [sp, #-4]!              @ *--sp = &fp
9193    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9194    mov     r0, r10                     @ r0<- self
9195    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9196    mov     r2, r9                      @ r2<- exception
9197    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9198    mov     r1, r1, asr #1              @ r1<- offset in code units
9199
9200    /* call, r0 gets catchRelPc (a code-unit offset) */
9201    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9202
9203    /* fix earlier stack overflow if necessary; may trash rFP */
9204    ldrb    r1, [r10, #offThread_stackOverflowed]
9205    cmp     r1, #0                      @ did we overflow earlier?
9206    beq     1f                          @ no, skip ahead
9207    mov     rFP, r0                     @ save relPc result in rFP
9208    mov     r0, r10                     @ r0<- self
9209    bl      dvmCleanupStackOverflow     @ call(self)
9210    mov     r0, rFP                     @ restore result
92111:
9212
9213    /* update frame pointer and check result from dvmFindCatchBlock */
9214    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9215    cmp     r0, #0                      @ is catchRelPc < 0?
9216    add     sp, sp, #8                  @ restore stack
9217    bmi     .LnotCaughtLocally
9218
9219    /* adjust locals to match self->curFrame and updated PC */
9220    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9221    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9222    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9223    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9224    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9225    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9226    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9227    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9228
9229    /* release the tracked alloc on the exception */
9230    mov     r0, r9                      @ r0<- exception
9231    mov     r1, r10                     @ r1<- self
9232    bl      dvmReleaseTrackedAlloc      @ release the exception
9233
9234    /* restore the exception if the handler wants it */
9235    FETCH_INST()                        @ load rINST from rPC
9236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9237    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9238    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9239    GOTO_OPCODE(ip)                     @ jump to next instruction
9240
9241.LnotCaughtLocally: @ r9=exception, r10=self
9242    /* fix stack overflow if necessary */
9243    ldrb    r1, [r10, #offThread_stackOverflowed]
9244    cmp     r1, #0                      @ did we overflow earlier?
9245    movne   r0, r10                     @ if yes: r0<- self
9246    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9247
9248    @ may want to show "not caught locally" debug messages here
9249#if DVM_SHOW_EXCEPTION >= 2
9250    /* call __android_log_print(prio, tag, format, ...) */
9251    /* "Exception %s from %s:%d not caught locally" */
9252    @ dvmLineNumFromPC(method, pc - method->insns)
9253    ldr     r0, [rGLUE, #offGlue_method]
9254    ldr     r1, [r0, #offMethod_insns]
9255    sub     r1, rPC, r1
9256    asr     r1, r1, #1
9257    bl      dvmLineNumFromPC
9258    str     r0, [sp, #-4]!
9259    @ dvmGetMethodSourceFile(method)
9260    ldr     r0, [rGLUE, #offGlue_method]
9261    bl      dvmGetMethodSourceFile
9262    str     r0, [sp, #-4]!
9263    @ exception->clazz->descriptor
9264    ldr     r3, [r9, #offObject_clazz]
9265    ldr     r3, [r3, #offClassObject_descriptor]
9266    @
9267    ldr     r2, strExceptionNotCaughtLocally
9268    ldr     r1, strLogTag
9269    mov     r0, #3                      @ LOG_DEBUG
9270    bl      __android_log_print
9271#endif
9272    str     r9, [r10, #offThread_exception] @ restore exception
9273    mov     r0, r9                      @ r0<- exception
9274    mov     r1, r10                     @ r1<- self
9275    bl      dvmReleaseTrackedAlloc      @ release the exception
9276    mov     r1, #0                      @ "want switch" = false
9277    b       common_gotoBail             @ bail out
9278
9279
9280    /*
9281     * Exception handling, calls through "glue code".
9282     */
9283    .if     0
9284.LexceptionOld:
9285    SAVE_PC_FP_TO_GLUE()                @ export state
9286    mov     r0, rGLUE                   @ arg to function
9287    bl      dvmMterp_exceptionThrown
9288    b       common_resumeAfterGlueCall
9289    .endif
9290
9291
9292/*
9293 * After returning from a "glued" function, pull out the updated
9294 * values and start executing at the next instruction.
9295 */
9296common_resumeAfterGlueCall:
9297    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9298    FETCH_INST()                        @ load rINST from rPC
9299    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9300    GOTO_OPCODE(ip)                     @ jump to next instruction
9301
9302/*
9303 * Invalid array index.
9304 */
9305common_errArrayIndex:
9306    EXPORT_PC()
9307    ldr     r0, strArrayIndexException
9308    mov     r1, #0
9309    bl      dvmThrowException
9310    b       common_exceptionThrown
9311
9312/*
9313 * Invalid array value.
9314 */
9315common_errArrayStore:
9316    EXPORT_PC()
9317    ldr     r0, strArrayStoreException
9318    mov     r1, #0
9319    bl      dvmThrowException
9320    b       common_exceptionThrown
9321
9322/*
9323 * Integer divide or mod by zero.
9324 */
9325common_errDivideByZero:
9326    EXPORT_PC()
9327    ldr     r0, strArithmeticException
9328    ldr     r1, strDivideByZero
9329    bl      dvmThrowException
9330    b       common_exceptionThrown
9331
9332/*
9333 * Attempt to allocate an array with a negative size.
9334 */
9335common_errNegativeArraySize:
9336    EXPORT_PC()
9337    ldr     r0, strNegativeArraySizeException
9338    mov     r1, #0
9339    bl      dvmThrowException
9340    b       common_exceptionThrown
9341
9342/*
9343 * Invocation of a non-existent method.
9344 */
9345common_errNoSuchMethod:
9346    EXPORT_PC()
9347    ldr     r0, strNoSuchMethodError
9348    mov     r1, #0
9349    bl      dvmThrowException
9350    b       common_exceptionThrown
9351
9352/*
9353 * We encountered a null object when we weren't expecting one.  We
9354 * export the PC, throw a NullPointerException, and goto the exception
9355 * processing code.
9356 */
9357common_errNullObject:
9358    EXPORT_PC()
9359    ldr     r0, strNullPointerException
9360    mov     r1, #0
9361    bl      dvmThrowException
9362    b       common_exceptionThrown
9363
9364/*
9365 * For debugging, cause an immediate fault.  The source address will
9366 * be in lr (use a bl instruction to jump here).
9367 */
9368common_abort:
9369    ldr     pc, .LdeadFood
9370.LdeadFood:
9371    .word   0xdeadf00d
9372
9373/*
9374 * Spit out a "we were here", preserving all registers.  (The attempt
9375 * to save ip won't work, but we need to save an even number of
9376 * registers for EABI 64-bit stack alignment.)
9377 */
9378    .macro  SQUEAK num
9379common_squeak\num:
9380    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9381    ldr     r0, strSqueak
9382    mov     r1, #\num
9383    bl      printf
9384    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9385    bx      lr
9386    .endm
9387
9388    SQUEAK  0
9389    SQUEAK  1
9390    SQUEAK  2
9391    SQUEAK  3
9392    SQUEAK  4
9393    SQUEAK  5
9394
9395/*
9396 * Spit out the number in r0, preserving registers.
9397 */
9398common_printNum:
9399    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9400    mov     r1, r0
9401    ldr     r0, strSqueak
9402    bl      printf
9403    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9404    bx      lr
9405
9406/*
9407 * Print a newline, preserving registers.
9408 */
9409common_printNewline:
9410    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9411    ldr     r0, strNewline
9412    bl      printf
9413    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9414    bx      lr
9415
9416    /*
9417     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9418     */
9419common_printHex:
9420    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9421    mov     r1, r0
9422    ldr     r0, strPrintHex
9423    bl      printf
9424    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9425    bx      lr
9426
9427/*
9428 * Print the 64-bit quantity in r0-r1, preserving registers.
9429 */
9430common_printLong:
9431    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9432    mov     r3, r1
9433    mov     r2, r0
9434    ldr     r0, strPrintLong
9435    bl      printf
9436    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9437    bx      lr
9438
9439/*
9440 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9441 */
9442common_printMethod:
9443    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9444    bl      dvmMterpPrintMethod
9445    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9446    bx      lr
9447
9448/*
9449 * Call a C helper function that dumps regs and possibly some
9450 * additional info.  Requires the C function to be compiled in.
9451 */
9452    .if     0
9453common_dumpRegs:
9454    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9455    bl      dvmMterpDumpArmRegs
9456    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9457    bx      lr
9458    .endif
9459
9460
9461/*
9462 * String references, must be close to the code that uses them.
9463 */
9464    .align  2
9465strArithmeticException:
9466    .word   .LstrArithmeticException
9467strArrayIndexException:
9468    .word   .LstrArrayIndexException
9469strArrayStoreException:
9470    .word   .LstrArrayStoreException
9471strDivideByZero:
9472    .word   .LstrDivideByZero
9473strNegativeArraySizeException:
9474    .word   .LstrNegativeArraySizeException
9475strNoSuchMethodError:
9476    .word   .LstrNoSuchMethodError
9477strNullPointerException:
9478    .word   .LstrNullPointerException
9479
9480strLogTag:
9481    .word   .LstrLogTag
9482strExceptionNotCaughtLocally:
9483    .word   .LstrExceptionNotCaughtLocally
9484
9485strNewline:
9486    .word   .LstrNewline
9487strSqueak:
9488    .word   .LstrSqueak
9489strPrintHex:
9490    .word   .LstrPrintHex
9491strPrintLong:
9492    .word   .LstrPrintLong
9493
9494/*
9495 * Zero-terminated ASCII string data.
9496 *
9497 * On ARM we have two choices: do like gcc does, and LDR from a .word
9498 * with the address, or use an ADR pseudo-op to get the address
9499 * directly.  ADR saves 4 bytes and an indirection, but it's using a
9500 * PC-relative addressing mode and hence has a limited range, which
9501 * makes it not work well with mergeable string sections.
9502 */
9503    .section .rodata.str1.4,"aMS",%progbits,1
9504
9505.LstrBadEntryPoint:
9506    .asciz  "Bad entry point %d\n"
9507.LstrArithmeticException:
9508    .asciz  "Ljava/lang/ArithmeticException;"
9509.LstrArrayIndexException:
9510    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9511.LstrArrayStoreException:
9512    .asciz  "Ljava/lang/ArrayStoreException;"
9513.LstrClassCastException:
9514    .asciz  "Ljava/lang/ClassCastException;"
9515.LstrDivideByZero:
9516    .asciz  "divide by zero"
9517.LstrFilledNewArrayNotImpl:
9518    .asciz  "filled-new-array only implemented for objects and 'int'"
9519.LstrInternalError:
9520    .asciz  "Ljava/lang/InternalError;"
9521.LstrInstantiationError:
9522    .asciz  "Ljava/lang/InstantiationError;"
9523.LstrNegativeArraySizeException:
9524    .asciz  "Ljava/lang/NegativeArraySizeException;"
9525.LstrNoSuchMethodError:
9526    .asciz  "Ljava/lang/NoSuchMethodError;"
9527.LstrNullPointerException:
9528    .asciz  "Ljava/lang/NullPointerException;"
9529
9530.LstrLogTag:
9531    .asciz  "mterp"
9532.LstrExceptionNotCaughtLocally:
9533    .asciz  "Exception %s from %s:%d not caught locally\n"
9534
9535.LstrNewline:
9536    .asciz  "\n"
9537.LstrSqueak:
9538    .asciz  "<%d>"
9539.LstrPrintHex:
9540    .asciz  "<0x%x>"
9541.LstrPrintLong:
9542    .asciz  "<%lld>"
9543
9544
9545