InterpAsm-armv5te-vfp.S revision 9797a237b48e880c33e2a2f497f48fb6f67c7a16
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
189#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204
205/* File: armv5te/platform.S */
206/*
207 * ===========================================================================
208 *  CPU-version-specific defines
209 * ===========================================================================
210 */
211
212/*
213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
214 * one-way branch.
215 *
216 * May modify IP.  Does not modify LR.
217 */
218.macro  LDR_PC source
219    ldr     pc, \source
220.endm
221
222/*
223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
224 * Jump to subroutine.
225 *
226 * May modify IP and LR.
227 */
228.macro  LDR_PC_LR source
229    mov     lr, pc
230    ldr     pc, \source
231.endm
232
233/*
234 * Macro for "LDMFD SP!, {...regs...,PC}".
235 *
236 * May modify IP and LR.
237 */
238.macro  LDMFD_PC regs
239    ldmfd   sp!, {\regs,pc}
240.endm
241
242
243/* File: armv5te/entry.S */
244/*
245 * Copyright (C) 2008 The Android Open Source Project
246 *
247 * Licensed under the Apache License, Version 2.0 (the "License");
248 * you may not use this file except in compliance with the License.
249 * You may obtain a copy of the License at
250 *
251 *      http://www.apache.org/licenses/LICENSE-2.0
252 *
253 * Unless required by applicable law or agreed to in writing, software
254 * distributed under the License is distributed on an "AS IS" BASIS,
255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
256 * See the License for the specific language governing permissions and
257 * limitations under the License.
258 */
259/*
260 * Interpreter entry point.
261 */
262
263/*
264 * We don't have formal stack frames, so gdb scans upward in the code
265 * to find the start of the function (a label with the %function type),
266 * and then looks at the next few instructions to figure out what
267 * got pushed onto the stack.  From this it figures out how to restore
268 * the registers, including PC, for the previous stack frame.  If gdb
269 * sees a non-function label, it stops scanning, so either we need to
270 * have nothing but assembler-local labels between the entry point and
271 * the break, or we need to fake it out.
272 *
273 * When this is defined, we add some stuff to make gdb less confused.
274 */
275#define ASSIST_DEBUGGER 1
276
277    .text
278    .align  2
279    .global dvmMterpStdRun
280    .type   dvmMterpStdRun, %function
281
282/*
283 * On entry:
284 *  r0  MterpGlue* glue
285 *
286 * This function returns a boolean "changeInterp" value.  The return comes
287 * via a call to dvmMterpStdBail().
288 */
289dvmMterpStdRun:
290#define MTERP_ENTRY1 \
291    .save {r4-r10,fp,lr}; \
292    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
293#define MTERP_ENTRY2 \
294    .pad    #4; \
295    sub     sp, sp, #4                  @ align 64
296
297    .fnstart
298    MTERP_ENTRY1
299    MTERP_ENTRY2
300
301    /* save stack pointer, add magic word for debuggerd */
302    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
303
304    /* set up "named" registers, figure out entry point */
305    mov     rGLUE, r0                   @ set rGLUE
306    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
307    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
308    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
309    cmp     r1, #kInterpEntryInstr      @ usual case?
310    bne     .Lnot_instr                 @ no, handle it
311
312#if defined(WITH_JIT)
313.Lno_singleStep:
314    /* Entry is always a possible trace start */
315    GET_JIT_PROF_TABLE(r0)
316    FETCH_INST()
317    cmp    r0,#0
318    bne    common_updateProfile
319    GET_INST_OPCODE(ip)
320    GOTO_OPCODE(ip)
321#else
322    /* start executing the instruction at rPC */
323    FETCH_INST()                        @ load rINST from rPC
324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
325    GOTO_OPCODE(ip)                     @ jump to next instruction
326#endif
327
328.Lnot_instr:
329    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
330    beq     common_returnFromMethod
331
332.Lnot_return:
333    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
334    beq     common_exceptionThrown
335
336#if defined(WITH_JIT)
337.Lnot_throw:
338    ldr     r0,[rGLUE, #offGlue_jitResume]
339    ldr     r2,[rGLUE, #offGlue_jitResumePC]
340    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
341    bne     .Lbad_arg
342    cmp     rPC,r2
343    bne     .Lno_singleStep             @ must have branched, don't resume
344    mov     r1, #kInterpEntryInstr
345    strb    r1, [rGLUE, #offGlue_entryPoint]
346    ldr     rINST, .LdvmCompilerTemplate
347    bx      r0                          @ re-enter the translation
348.LdvmCompilerTemplate:
349    .word   dvmCompilerTemplateStart
350#endif
351
352.Lbad_arg:
353    ldr     r0, strBadEntryPoint
354    @ r1 holds value of entryPoint
355    bl      printf
356    bl      dvmAbort
357    .fnend
358
359
360    .global dvmMterpStdBail
361    .type   dvmMterpStdBail, %function
362
363/*
364 * Restore the stack pointer and PC from the save point established on entry.
365 * This is essentially the same as a longjmp, but should be cheaper.  The
366 * last instruction causes us to return to whoever called dvmMterpStdRun.
367 *
368 * We pushed some registers on the stack in dvmMterpStdRun, then saved
369 * SP and LR.  Here we restore SP, restore the registers, and then restore
370 * LR to PC.
371 *
372 * On entry:
373 *  r0  MterpGlue* glue
374 *  r1  bool changeInterp
375 */
376dvmMterpStdBail:
377    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
378    mov     r0, r1                          @ return the changeInterp value
379    add     sp, sp, #4                      @ un-align 64
380    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
381
382
383/*
384 * String references.
385 */
386strBadEntryPoint:
387    .word   .LstrBadEntryPoint
388
389
390
391    .global dvmAsmInstructionStart
392    .type   dvmAsmInstructionStart, %function
393dvmAsmInstructionStart = .L_OP_NOP
394    .text
395
396/* ------------------------------ */
397    .balign 64
398.L_OP_NOP: /* 0x00 */
399/* File: armv5te/OP_NOP.S */
400    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
401    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
402    GOTO_OPCODE(ip)                     @ execute it
403
404#ifdef ASSIST_DEBUGGER
405    /* insert fake function header to help gdb find the stack frame */
406    .type   dalvik_inst, %function
407dalvik_inst:
408    .fnstart
409    MTERP_ENTRY1
410    MTERP_ENTRY2
411    .fnend
412#endif
413
414
415/* ------------------------------ */
416    .balign 64
417.L_OP_MOVE: /* 0x01 */
418/* File: armv5te/OP_MOVE.S */
419    /* for move, move-object, long-to-int */
420    /* op vA, vB */
421    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
422    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
423    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
424    GET_VREG(r2, r1)                    @ r2<- fp[B]
425    and     r0, r0, #15
426    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
427    SET_VREG(r2, r0)                    @ fp[A]<- r2
428    GOTO_OPCODE(ip)                     @ execute next instruction
429
430
431/* ------------------------------ */
432    .balign 64
433.L_OP_MOVE_FROM16: /* 0x02 */
434/* File: armv5te/OP_MOVE_FROM16.S */
435    /* for: move/from16, move-object/from16 */
436    /* op vAA, vBBBB */
437    FETCH(r1, 1)                        @ r1<- BBBB
438    mov     r0, rINST, lsr #8           @ r0<- AA
439    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
440    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
442    SET_VREG(r2, r0)                    @ fp[AA]<- r2
443    GOTO_OPCODE(ip)                     @ jump to next instruction
444
445
446/* ------------------------------ */
447    .balign 64
448.L_OP_MOVE_16: /* 0x03 */
449/* File: armv5te/OP_MOVE_16.S */
450    /* for: move/16, move-object/16 */
451    /* op vAAAA, vBBBB */
452    FETCH(r1, 2)                        @ r1<- BBBB
453    FETCH(r0, 1)                        @ r0<- AAAA
454    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
455    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
457    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
458    GOTO_OPCODE(ip)                     @ jump to next instruction
459
460
461/* ------------------------------ */
462    .balign 64
463.L_OP_MOVE_WIDE: /* 0x04 */
464/* File: armv5te/OP_MOVE_WIDE.S */
465    /* move-wide vA, vB */
466    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
467    mov     r2, rINST, lsr #8           @ r2<- A(+)
468    mov     r3, rINST, lsr #12          @ r3<- B
469    and     r2, r2, #15
470    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
471    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
472    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
473    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
475    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
476    GOTO_OPCODE(ip)                     @ jump to next instruction
477
478
479/* ------------------------------ */
480    .balign 64
481.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
482/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
483    /* move-wide/from16 vAA, vBBBB */
484    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
485    FETCH(r3, 1)                        @ r3<- BBBB
486    mov     r2, rINST, lsr #8           @ r2<- AA
487    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
488    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
489    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
490    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
492    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
493    GOTO_OPCODE(ip)                     @ jump to next instruction
494
495
496/* ------------------------------ */
497    .balign 64
498.L_OP_MOVE_WIDE_16: /* 0x06 */
499/* File: armv5te/OP_MOVE_WIDE_16.S */
500    /* move-wide/16 vAAAA, vBBBB */
501    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
502    FETCH(r3, 2)                        @ r3<- BBBB
503    FETCH(r2, 1)                        @ r2<- AAAA
504    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
505    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
506    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
507    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
509    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
510    GOTO_OPCODE(ip)                     @ jump to next instruction
511
512
513/* ------------------------------ */
514    .balign 64
515.L_OP_MOVE_OBJECT: /* 0x07 */
516/* File: armv5te/OP_MOVE_OBJECT.S */
517/* File: armv5te/OP_MOVE.S */
518    /* for move, move-object, long-to-int */
519    /* op vA, vB */
520    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
521    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
522    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
523    GET_VREG(r2, r1)                    @ r2<- fp[B]
524    and     r0, r0, #15
525    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
526    SET_VREG(r2, r0)                    @ fp[A]<- r2
527    GOTO_OPCODE(ip)                     @ execute next instruction
528
529
530
531/* ------------------------------ */
532    .balign 64
533.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
534/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
535/* File: armv5te/OP_MOVE_FROM16.S */
536    /* for: move/from16, move-object/from16 */
537    /* op vAA, vBBBB */
538    FETCH(r1, 1)                        @ r1<- BBBB
539    mov     r0, rINST, lsr #8           @ r0<- AA
540    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
541    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
542    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
543    SET_VREG(r2, r0)                    @ fp[AA]<- r2
544    GOTO_OPCODE(ip)                     @ jump to next instruction
545
546
547
548/* ------------------------------ */
549    .balign 64
550.L_OP_MOVE_OBJECT_16: /* 0x09 */
551/* File: armv5te/OP_MOVE_OBJECT_16.S */
552/* File: armv5te/OP_MOVE_16.S */
553    /* for: move/16, move-object/16 */
554    /* op vAAAA, vBBBB */
555    FETCH(r1, 2)                        @ r1<- BBBB
556    FETCH(r0, 1)                        @ r0<- AAAA
557    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
558    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
559    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
560    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
561    GOTO_OPCODE(ip)                     @ jump to next instruction
562
563
564
565/* ------------------------------ */
566    .balign 64
567.L_OP_MOVE_RESULT: /* 0x0a */
568/* File: armv5te/OP_MOVE_RESULT.S */
569    /* for: move-result, move-result-object */
570    /* op vAA */
571    mov     r2, rINST, lsr #8           @ r2<- AA
572    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
573    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
574    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
575    SET_VREG(r0, r2)                    @ fp[AA]<- r0
576    GOTO_OPCODE(ip)                     @ jump to next instruction
577
578
579/* ------------------------------ */
580    .balign 64
581.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
582/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
583    /* move-result-wide vAA */
584    mov     r2, rINST, lsr #8           @ r2<- AA
585    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
586    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
587    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
588    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
589    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
590    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
591    GOTO_OPCODE(ip)                     @ jump to next instruction
592
593
594/* ------------------------------ */
595    .balign 64
596.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
597/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
598/* File: armv5te/OP_MOVE_RESULT.S */
599    /* for: move-result, move-result-object */
600    /* op vAA */
601    mov     r2, rINST, lsr #8           @ r2<- AA
602    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
603    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
604    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
605    SET_VREG(r0, r2)                    @ fp[AA]<- r0
606    GOTO_OPCODE(ip)                     @ jump to next instruction
607
608
609
610/* ------------------------------ */
611    .balign 64
612.L_OP_MOVE_EXCEPTION: /* 0x0d */
613/* File: armv5te/OP_MOVE_EXCEPTION.S */
614    /* move-exception vAA */
615    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
616    mov     r2, rINST, lsr #8           @ r2<- AA
617    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
618    mov     r1, #0                      @ r1<- 0
619    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
620    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
621    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
622    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
623    GOTO_OPCODE(ip)                     @ jump to next instruction
624
625
626/* ------------------------------ */
627    .balign 64
628.L_OP_RETURN_VOID: /* 0x0e */
629/* File: armv5te/OP_RETURN_VOID.S */
630    b       common_returnFromMethod
631
632
633/* ------------------------------ */
634    .balign 64
635.L_OP_RETURN: /* 0x0f */
636/* File: armv5te/OP_RETURN.S */
637    /*
638     * Return a 32-bit value.  Copies the return value into the "glue"
639     * structure, then jumps to the return handler.
640     *
641     * for: return, return-object
642     */
643    /* op vAA */
644    mov     r2, rINST, lsr #8           @ r2<- AA
645    GET_VREG(r0, r2)                    @ r0<- vAA
646    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
647    b       common_returnFromMethod
648
649
650/* ------------------------------ */
651    .balign 64
652.L_OP_RETURN_WIDE: /* 0x10 */
653/* File: armv5te/OP_RETURN_WIDE.S */
654    /*
655     * Return a 64-bit value.  Copies the return value into the "glue"
656     * structure, then jumps to the return handler.
657     */
658    /* return-wide vAA */
659    mov     r2, rINST, lsr #8           @ r2<- AA
660    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
661    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
662    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
663    stmia   r3, {r0-r1}                 @ retval<- r0/r1
664    b       common_returnFromMethod
665
666
667/* ------------------------------ */
668    .balign 64
669.L_OP_RETURN_OBJECT: /* 0x11 */
670/* File: armv5te/OP_RETURN_OBJECT.S */
671/* File: armv5te/OP_RETURN.S */
672    /*
673     * Return a 32-bit value.  Copies the return value into the "glue"
674     * structure, then jumps to the return handler.
675     *
676     * for: return, return-object
677     */
678    /* op vAA */
679    mov     r2, rINST, lsr #8           @ r2<- AA
680    GET_VREG(r0, r2)                    @ r0<- vAA
681    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
682    b       common_returnFromMethod
683
684
685
686/* ------------------------------ */
687    .balign 64
688.L_OP_CONST_4: /* 0x12 */
689/* File: armv5te/OP_CONST_4.S */
690    /* const/4 vA, #+B */
691    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
692    mov     r0, rINST, lsr #8           @ r0<- A+
693    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
694    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
695    and     r0, r0, #15
696    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
697    SET_VREG(r1, r0)                    @ fp[A]<- r1
698    GOTO_OPCODE(ip)                     @ execute next instruction
699
700
701/* ------------------------------ */
702    .balign 64
703.L_OP_CONST_16: /* 0x13 */
704/* File: armv5te/OP_CONST_16.S */
705    /* const/16 vAA, #+BBBB */
706    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
707    mov     r3, rINST, lsr #8           @ r3<- AA
708    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
709    SET_VREG(r0, r3)                    @ vAA<- r0
710    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
711    GOTO_OPCODE(ip)                     @ jump to next instruction
712
713
714/* ------------------------------ */
715    .balign 64
716.L_OP_CONST: /* 0x14 */
717/* File: armv5te/OP_CONST.S */
718    /* const vAA, #+BBBBbbbb */
719    mov     r3, rINST, lsr #8           @ r3<- AA
720    FETCH(r0, 1)                        @ r0<- bbbb (low)
721    FETCH(r1, 2)                        @ r1<- BBBB (high)
722    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
723    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
724    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
725    SET_VREG(r0, r3)                    @ vAA<- r0
726    GOTO_OPCODE(ip)                     @ jump to next instruction
727
728
729/* ------------------------------ */
730    .balign 64
731.L_OP_CONST_HIGH16: /* 0x15 */
732/* File: armv5te/OP_CONST_HIGH16.S */
733    /* const/high16 vAA, #+BBBB0000 */
734    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
735    mov     r3, rINST, lsr #8           @ r3<- AA
736    mov     r0, r0, lsl #16             @ r0<- BBBB0000
737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
738    SET_VREG(r0, r3)                    @ vAA<- r0
739    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
740    GOTO_OPCODE(ip)                     @ jump to next instruction
741
742
743/* ------------------------------ */
744    .balign 64
745.L_OP_CONST_WIDE_16: /* 0x16 */
746/* File: armv5te/OP_CONST_WIDE_16.S */
747    /* const-wide/16 vAA, #+BBBB */
748    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
749    mov     r3, rINST, lsr #8           @ r3<- AA
750    mov     r1, r0, asr #31             @ r1<- ssssssss
751    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
752    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
754    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
755    GOTO_OPCODE(ip)                     @ jump to next instruction
756
757
758/* ------------------------------ */
759    .balign 64
760.L_OP_CONST_WIDE_32: /* 0x17 */
761/* File: armv5te/OP_CONST_WIDE_32.S */
762    /* const-wide/32 vAA, #+BBBBbbbb */
763    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
764    mov     r3, rINST, lsr #8           @ r3<- AA
765    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
766    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
767    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
768    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
769    mov     r1, r0, asr #31             @ r1<- ssssssss
770    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
771    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
772    GOTO_OPCODE(ip)                     @ jump to next instruction
773
774
775/* ------------------------------ */
776    .balign 64
777.L_OP_CONST_WIDE: /* 0x18 */
778/* File: armv5te/OP_CONST_WIDE.S */
779    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
780    FETCH(r0, 1)                        @ r0<- bbbb (low)
781    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
782    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
783    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
784    FETCH(r3, 4)                        @ r3<- HHHH (high)
785    mov     r9, rINST, lsr #8           @ r9<- AA
786    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
787    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
788    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
790    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
791    GOTO_OPCODE(ip)                     @ jump to next instruction
792
793
794/* ------------------------------ */
795    .balign 64
796.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
797/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
798    /* const-wide/high16 vAA, #+BBBB000000000000 */
799    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
800    mov     r3, rINST, lsr #8           @ r3<- AA
801    mov     r0, #0                      @ r0<- 00000000
802    mov     r1, r1, lsl #16             @ r1<- BBBB0000
803    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
804    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
805    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
806    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
807    GOTO_OPCODE(ip)                     @ jump to next instruction
808
809
810/* ------------------------------ */
811    .balign 64
812.L_OP_CONST_STRING: /* 0x1a */
813/* File: armv5te/OP_CONST_STRING.S */
814    /* const/string vAA, String@BBBB */
815    FETCH(r1, 1)                        @ r1<- BBBB
816    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
817    mov     r9, rINST, lsr #8           @ r9<- AA
818    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
819    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
820    cmp     r0, #0                      @ not yet resolved?
821    beq     .LOP_CONST_STRING_resolve
822    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
823    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
824    SET_VREG(r0, r9)                    @ vAA<- r0
825    GOTO_OPCODE(ip)                     @ jump to next instruction
826
827/* ------------------------------ */
828    .balign 64
829.L_OP_CONST_STRING_JUMBO: /* 0x1b */
830/* File: armv5te/OP_CONST_STRING_JUMBO.S */
831    /* const/string vAA, String@BBBBBBBB */
832    FETCH(r0, 1)                        @ r0<- bbbb (low)
833    FETCH(r1, 2)                        @ r1<- BBBB (high)
834    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
835    mov     r9, rINST, lsr #8           @ r9<- AA
836    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
837    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
838    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
839    cmp     r0, #0
840    beq     .LOP_CONST_STRING_JUMBO_resolve
841    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
842    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
843    SET_VREG(r0, r9)                    @ vAA<- r0
844    GOTO_OPCODE(ip)                     @ jump to next instruction
845
846/* ------------------------------ */
847    .balign 64
848.L_OP_CONST_CLASS: /* 0x1c */
849/* File: armv5te/OP_CONST_CLASS.S */
850    /* const/class vAA, Class@BBBB */
851    FETCH(r1, 1)                        @ r1<- BBBB
852    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
853    mov     r9, rINST, lsr #8           @ r9<- AA
854    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
855    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
856    cmp     r0, #0                      @ not yet resolved?
857    beq     .LOP_CONST_CLASS_resolve
858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
859    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
860    SET_VREG(r0, r9)                    @ vAA<- r0
861    GOTO_OPCODE(ip)                     @ jump to next instruction
862
863/* ------------------------------ */
864    .balign 64
865.L_OP_MONITOR_ENTER: /* 0x1d */
866/* File: armv5te/OP_MONITOR_ENTER.S */
867    /*
868     * Synchronize on an object.
869     */
870    /* monitor-enter vAA */
871    mov     r2, rINST, lsr #8           @ r2<- AA
872    GET_VREG(r1, r2)                    @ r1<- vAA (object)
873    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
874    cmp     r1, #0                      @ null object?
875    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
876    beq     common_errNullObject        @ null object, throw an exception
877    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
878    bl      dvmLockObject               @ call(self, obj)
879#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
880    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
881    ldr     r1, [r0, #offThread_exception] @ check for exception
882    cmp     r1, #0
883    bne     common_exceptionThrown      @ exception raised, bail out
884#endif
885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
886    GOTO_OPCODE(ip)                     @ jump to next instruction
887
888
889/* ------------------------------ */
890    .balign 64
891.L_OP_MONITOR_EXIT: /* 0x1e */
892/* File: armv5te/OP_MONITOR_EXIT.S */
893    /*
894     * Unlock an object.
895     *
896     * Exceptions that occur when unlocking a monitor need to appear as
897     * if they happened at the following instruction.  See the Dalvik
898     * instruction spec.
899     */
900    /* monitor-exit vAA */
901    mov     r2, rINST, lsr #8           @ r2<- AA
902    EXPORT_PC()                         @ before fetch: export the PC
903    GET_VREG(r1, r2)                    @ r1<- vAA (object)
904    cmp     r1, #0                      @ null object?
905    beq     common_errNullObject        @ yes
906    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
907    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
908    cmp     r0, #0                      @ failed?
909    beq     common_exceptionThrown      @ yes, exception is pending
910    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
912    GOTO_OPCODE(ip)                     @ jump to next instruction
913
914
915/* ------------------------------ */
916    .balign 64
917.L_OP_CHECK_CAST: /* 0x1f */
918/* File: armv5te/OP_CHECK_CAST.S */
919    /*
920     * Check to see if a cast from one class to another is allowed.
921     */
922    /* check-cast vAA, class@BBBB */
923    mov     r3, rINST, lsr #8           @ r3<- AA
924    FETCH(r2, 1)                        @ r2<- BBBB
925    GET_VREG(r9, r3)                    @ r9<- object
926    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
927    cmp     r9, #0                      @ is object null?
928    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
929    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
930    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
931    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
932    cmp     r1, #0                      @ have we resolved this before?
933    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
934.LOP_CHECK_CAST_resolved:
935    cmp     r0, r1                      @ same class (trivial success)?
936    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
937.LOP_CHECK_CAST_okay:
938    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
940    GOTO_OPCODE(ip)                     @ jump to next instruction
941
942/* ------------------------------ */
943    .balign 64
944.L_OP_INSTANCE_OF: /* 0x20 */
945/* File: armv5te/OP_INSTANCE_OF.S */
946    /*
947     * Check to see if an object reference is an instance of a class.
948     *
949     * Most common situation is a non-null object, being compared against
950     * an already-resolved class.
951     */
952    /* instance-of vA, vB, class@CCCC */
953    mov     r3, rINST, lsr #12          @ r3<- B
954    mov     r9, rINST, lsr #8           @ r9<- A+
955    GET_VREG(r0, r3)                    @ r0<- vB (object)
956    and     r9, r9, #15                 @ r9<- A
957    cmp     r0, #0                      @ is object null?
958    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
959    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
960    FETCH(r3, 1)                        @ r3<- CCCC
961    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
962    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
963    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
964    cmp     r1, #0                      @ have we resolved this before?
965    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
966.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
967    cmp     r0, r1                      @ same class (trivial success)?
968    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
969    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
970
971/* ------------------------------ */
972    .balign 64
973.L_OP_ARRAY_LENGTH: /* 0x21 */
974/* File: armv5te/OP_ARRAY_LENGTH.S */
975    /*
976     * Return the length of an array.
977     */
978    mov     r1, rINST, lsr #12          @ r1<- B
979    mov     r2, rINST, lsr #8           @ r2<- A+
980    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
981    and     r2, r2, #15                 @ r2<- A
982    cmp     r0, #0                      @ is object null?
983    beq     common_errNullObject        @ yup, fail
984    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
985    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
987    SET_VREG(r3, r2)                    @ vB<- length
988    GOTO_OPCODE(ip)                     @ jump to next instruction
989
990
991/* ------------------------------ */
992    .balign 64
993.L_OP_NEW_INSTANCE: /* 0x22 */
994/* File: armv5te/OP_NEW_INSTANCE.S */
995    /*
996     * Create a new instance of a class.
997     */
998    /* new-instance vAA, class@BBBB */
999    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1000    FETCH(r1, 1)                        @ r1<- BBBB
1001    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1002    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1003    EXPORT_PC()                         @ req'd for init, resolve, alloc
1004    cmp     r0, #0                      @ already resolved?
1005    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1006.LOP_NEW_INSTANCE_resolved:   @ r0=class
1007    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1008    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1009    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1010.LOP_NEW_INSTANCE_initialized: @ r0=class
1011    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1012    bl      dvmAllocObject              @ r0<- new object
1013    b       .LOP_NEW_INSTANCE_finish          @ continue
1014
1015/* ------------------------------ */
1016    .balign 64
1017.L_OP_NEW_ARRAY: /* 0x23 */
1018/* File: armv5te/OP_NEW_ARRAY.S */
1019    /*
1020     * Allocate an array of objects, specified with the array class
1021     * and a count.
1022     *
1023     * The verifier guarantees that this is an array class, so we don't
1024     * check for it here.
1025     */
1026    /* new-array vA, vB, class@CCCC */
1027    mov     r0, rINST, lsr #12          @ r0<- B
1028    FETCH(r2, 1)                        @ r2<- CCCC
1029    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1030    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1031    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1032    cmp     r1, #0                      @ check length
1033    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1034    bmi     common_errNegativeArraySize @ negative length, bail
1035    cmp     r0, #0                      @ already resolved?
1036    EXPORT_PC()                         @ req'd for resolve, alloc
1037    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1038    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1039
1040/* ------------------------------ */
1041    .balign 64
1042.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1043/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1044    /*
1045     * Create a new array with elements filled from registers.
1046     *
1047     * for: filled-new-array, filled-new-array/range
1048     */
1049    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1050    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1051    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1052    FETCH(r1, 1)                        @ r1<- BBBB
1053    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1054    EXPORT_PC()                         @ need for resolve and alloc
1055    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1056    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1057    cmp     r0, #0                      @ already resolved?
1058    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10598:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1060    mov     r2, #0                      @ r2<- false
1061    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1062    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1063    cmp     r0, #0                      @ got null?
1064    beq     common_exceptionThrown      @ yes, handle exception
1065    b       .LOP_FILLED_NEW_ARRAY_continue
1066
1067/* ------------------------------ */
1068    .balign 64
1069.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1070/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1071/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1072    /*
1073     * Create a new array with elements filled from registers.
1074     *
1075     * for: filled-new-array, filled-new-array/range
1076     */
1077    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1078    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1079    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1080    FETCH(r1, 1)                        @ r1<- BBBB
1081    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1082    EXPORT_PC()                         @ need for resolve and alloc
1083    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1084    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1085    cmp     r0, #0                      @ already resolved?
1086    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10878:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1088    mov     r2, #0                      @ r2<- false
1089    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1090    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1091    cmp     r0, #0                      @ got null?
1092    beq     common_exceptionThrown      @ yes, handle exception
1093    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1094
1095
1096/* ------------------------------ */
1097    .balign 64
1098.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1099/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1100    /* fill-array-data vAA, +BBBBBBBB */
1101    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1102    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1103    mov     r3, rINST, lsr #8           @ r3<- AA
1104    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1105    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1106    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1107    EXPORT_PC();
1108    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1109    cmp     r0, #0                      @ 0 means an exception is thrown
1110    beq     common_exceptionThrown      @ has exception
1111    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1113    GOTO_OPCODE(ip)                     @ jump to next instruction
1114
1115/* ------------------------------ */
1116    .balign 64
1117.L_OP_THROW: /* 0x27 */
1118/* File: armv5te/OP_THROW.S */
1119    /*
1120     * Throw an exception object in the current thread.
1121     */
1122    /* throw vAA */
1123    mov     r2, rINST, lsr #8           @ r2<- AA
1124    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1125    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1126    cmp     r1, #0                      @ null object?
1127    beq     common_errNullObject        @ yes, throw an NPE instead
1128    @ bypass dvmSetException, just store it
1129    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1130    b       common_exceptionThrown
1131
1132
1133/* ------------------------------ */
1134    .balign 64
1135.L_OP_GOTO: /* 0x28 */
1136/* File: armv5te/OP_GOTO.S */
1137    /*
1138     * Unconditional branch, 8-bit offset.
1139     *
1140     * The branch distance is a signed code-unit offset, which we need to
1141     * double to get a byte offset.
1142     */
1143    /* goto +AA */
1144    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1145    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1146    mov     r9, r9, lsl #1              @ r9<- byte offset
1147    bmi     common_backwardBranch       @ backward branch, do periodic checks
1148#if defined(WITH_JIT)
1149    GET_JIT_PROF_TABLE(r0)
1150    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1151    cmp     r0,#0
1152    bne     common_updateProfile
1153    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1154    GOTO_OPCODE(ip)                     @ jump to next instruction
1155#else
1156    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1158    GOTO_OPCODE(ip)                     @ jump to next instruction
1159#endif
1160
1161/* ------------------------------ */
1162    .balign 64
1163.L_OP_GOTO_16: /* 0x29 */
1164/* File: armv5te/OP_GOTO_16.S */
1165    /*
1166     * Unconditional branch, 16-bit offset.
1167     *
1168     * The branch distance is a signed code-unit offset, which we need to
1169     * double to get a byte offset.
1170     */
1171    /* goto/16 +AAAA */
1172    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1173    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1174    bmi     common_backwardBranch       @ backward branch, do periodic checks
1175#if defined(WITH_JIT)
1176    GET_JIT_PROF_TABLE(r0)
1177    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1178    cmp     r0,#0
1179    bne     common_updateProfile
1180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1181    GOTO_OPCODE(ip)                     @ jump to next instruction
1182#else
1183    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1185    GOTO_OPCODE(ip)                     @ jump to next instruction
1186#endif
1187
1188
1189/* ------------------------------ */
1190    .balign 64
1191.L_OP_GOTO_32: /* 0x2a */
1192/* File: armv5te/OP_GOTO_32.S */
1193    /*
1194     * Unconditional branch, 32-bit offset.
1195     *
1196     * The branch distance is a signed code-unit offset, which we need to
1197     * double to get a byte offset.
1198     *
1199     * Unlike most opcodes, this one is allowed to branch to itself, so
1200     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1201     * instruction doesn't affect the V flag, so we need to clear it
1202     * explicitly.
1203     */
1204    /* goto/32 +AAAAAAAA */
1205    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1206    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1207    cmp     ip, ip                      @ (clear V flag during stall)
1208    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1209    mov     r9, r0, asl #1              @ r9<- byte offset
1210    ble     common_backwardBranch       @ backward branch, do periodic checks
1211#if defined(WITH_JIT)
1212    GET_JIT_PROF_TABLE(r0)
1213    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1214    cmp     r0,#0
1215    bne     common_updateProfile
1216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1217    GOTO_OPCODE(ip)                     @ jump to next instruction
1218#else
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#endif
1223
1224/* ------------------------------ */
1225    .balign 64
1226.L_OP_PACKED_SWITCH: /* 0x2b */
1227/* File: armv5te/OP_PACKED_SWITCH.S */
1228    /*
1229     * Handle a packed-switch or sparse-switch instruction.  In both cases
1230     * we decode it and hand it off to a helper function.
1231     *
1232     * We don't really expect backward branches in a switch statement, but
1233     * they're perfectly legal, so we check for them here.
1234     *
1235     * for: packed-switch, sparse-switch
1236     */
1237    /* op vAA, +BBBB */
1238    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1239    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1240    mov     r3, rINST, lsr #8           @ r3<- AA
1241    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1242    GET_VREG(r1, r3)                    @ r1<- vAA
1243    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1244    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1245    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1246    bmi     common_backwardBranch       @ backward branch, do periodic checks
1247    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1248#if defined(WITH_JIT)
1249    GET_JIT_PROF_TABLE(r0)
1250    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1251    cmp     r0,#0
1252    bne     common_updateProfile
1253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1254    GOTO_OPCODE(ip)                     @ jump to next instruction
1255#else
1256    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1258    GOTO_OPCODE(ip)                     @ jump to next instruction
1259#endif
1260
1261
1262/* ------------------------------ */
1263    .balign 64
1264.L_OP_SPARSE_SWITCH: /* 0x2c */
1265/* File: armv5te/OP_SPARSE_SWITCH.S */
1266/* File: armv5te/OP_PACKED_SWITCH.S */
1267    /*
1268     * Handle a packed-switch or sparse-switch instruction.  In both cases
1269     * we decode it and hand it off to a helper function.
1270     *
1271     * We don't really expect backward branches in a switch statement, but
1272     * they're perfectly legal, so we check for them here.
1273     *
1274     * for: packed-switch, sparse-switch
1275     */
1276    /* op vAA, +BBBB */
1277    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1278    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1279    mov     r3, rINST, lsr #8           @ r3<- AA
1280    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1281    GET_VREG(r1, r3)                    @ r1<- vAA
1282    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1283    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1284    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1285    bmi     common_backwardBranch       @ backward branch, do periodic checks
1286    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1287#if defined(WITH_JIT)
1288    GET_JIT_PROF_TABLE(r0)
1289    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1290    cmp     r0,#0
1291    bne     common_updateProfile
1292    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1293    GOTO_OPCODE(ip)                     @ jump to next instruction
1294#else
1295    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1297    GOTO_OPCODE(ip)                     @ jump to next instruction
1298#endif
1299
1300
1301
1302/* ------------------------------ */
1303    .balign 64
1304.L_OP_CMPL_FLOAT: /* 0x2d */
1305/* File: arm-vfp/OP_CMPL_FLOAT.S */
1306    /*
1307     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1308     * destination register based on the results of the comparison.
1309     *
1310     * int compare(x, y) {
1311     *     if (x == y) {
1312     *         return 0;
1313     *     } else if (x > y) {
1314     *         return 1;
1315     *     } else if (x < y) {
1316     *         return -1;
1317     *     } else {
1318     *         return -1;
1319     *     }
1320     * }
1321     */
1322    /* op vAA, vBB, vCC */
1323    FETCH(r0, 1)                        @ r0<- CCBB
1324    mov     r9, rINST, lsr #8           @ r9<- AA
1325    and     r2, r0, #255                @ r2<- BB
1326    mov     r3, r0, lsr #8              @ r3<- CC
1327    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1328    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1329    flds    s0, [r2]                    @ s0<- vBB
1330    flds    s1, [r3]                    @ s1<- vCC
1331    fcmpes  s0, s1                      @ compare (vBB, vCC)
1332    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1333    mvn     r0, #0                      @ r0<- -1 (default)
1334    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1335    fmstat                              @ export status flags
1336    movgt   r0, #1                      @ (greater than) r1<- 1
1337    moveq   r0, #0                      @ (equal) r1<- 0
1338    b       .LOP_CMPL_FLOAT_finish          @ argh
1339
1340
1341/* ------------------------------ */
1342    .balign 64
1343.L_OP_CMPG_FLOAT: /* 0x2e */
1344/* File: arm-vfp/OP_CMPG_FLOAT.S */
1345    /*
1346     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1347     * destination register based on the results of the comparison.
1348     *
1349     * int compare(x, y) {
1350     *     if (x == y) {
1351     *         return 0;
1352     *     } else if (x < y) {
1353     *         return -1;
1354     *     } else if (x > y) {
1355     *         return 1;
1356     *     } else {
1357     *         return 1;
1358     *     }
1359     * }
1360     */
1361    /* op vAA, vBB, vCC */
1362    FETCH(r0, 1)                        @ r0<- CCBB
1363    mov     r9, rINST, lsr #8           @ r9<- AA
1364    and     r2, r0, #255                @ r2<- BB
1365    mov     r3, r0, lsr #8              @ r3<- CC
1366    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1367    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1368    flds    s0, [r2]                    @ s0<- vBB
1369    flds    s1, [r3]                    @ s1<- vCC
1370    fcmpes  s0, s1                      @ compare (vBB, vCC)
1371    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1372    mov     r0, #1                      @ r0<- 1 (default)
1373    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1374    fmstat                              @ export status flags
1375    mvnmi   r0, #0                      @ (less than) r1<- -1
1376    moveq   r0, #0                      @ (equal) r1<- 0
1377    b       .LOP_CMPG_FLOAT_finish          @ argh
1378
1379
1380/* ------------------------------ */
1381    .balign 64
1382.L_OP_CMPL_DOUBLE: /* 0x2f */
1383/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1384    /*
1385     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1386     * destination register based on the results of the comparison.
1387     *
1388     * int compare(x, y) {
1389     *     if (x == y) {
1390     *         return 0;
1391     *     } else if (x > y) {
1392     *         return 1;
1393     *     } else if (x < y) {
1394     *         return -1;
1395     *     } else {
1396     *         return -1;
1397     *     }
1398     * }
1399     */
1400    /* op vAA, vBB, vCC */
1401    FETCH(r0, 1)                        @ r0<- CCBB
1402    mov     r9, rINST, lsr #8           @ r9<- AA
1403    and     r2, r0, #255                @ r2<- BB
1404    mov     r3, r0, lsr #8              @ r3<- CC
1405    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1406    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1407    fldd    d0, [r2]                    @ d0<- vBB
1408    fldd    d1, [r3]                    @ d1<- vCC
1409    fcmped  d0, d1                      @ compare (vBB, vCC)
1410    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1411    mvn     r0, #0                      @ r0<- -1 (default)
1412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1413    fmstat                              @ export status flags
1414    movgt   r0, #1                      @ (greater than) r1<- 1
1415    moveq   r0, #0                      @ (equal) r1<- 0
1416    b       .LOP_CMPL_DOUBLE_finish          @ argh
1417
1418
1419/* ------------------------------ */
1420    .balign 64
1421.L_OP_CMPG_DOUBLE: /* 0x30 */
1422/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1423    /*
1424     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1425     * destination register based on the results of the comparison.
1426     *
1427     * int compare(x, y) {
1428     *     if (x == y) {
1429     *         return 0;
1430     *     } else if (x < y) {
1431     *         return -1;
1432     *     } else if (x > y) {
1433     *         return 1;
1434     *     } else {
1435     *         return 1;
1436     *     }
1437     * }
1438     */
1439    /* op vAA, vBB, vCC */
1440    FETCH(r0, 1)                        @ r0<- CCBB
1441    mov     r9, rINST, lsr #8           @ r9<- AA
1442    and     r2, r0, #255                @ r2<- BB
1443    mov     r3, r0, lsr #8              @ r3<- CC
1444    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1445    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1446    fldd    d0, [r2]                    @ d0<- vBB
1447    fldd    d1, [r3]                    @ d1<- vCC
1448    fcmped  d0, d1                      @ compare (vBB, vCC)
1449    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1450    mov     r0, #1                      @ r0<- 1 (default)
1451    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1452    fmstat                              @ export status flags
1453    mvnmi   r0, #0                      @ (less than) r1<- -1
1454    moveq   r0, #0                      @ (equal) r1<- 0
1455    b       .LOP_CMPG_DOUBLE_finish          @ argh
1456
1457
1458/* ------------------------------ */
1459    .balign 64
1460.L_OP_CMP_LONG: /* 0x31 */
1461/* File: armv5te/OP_CMP_LONG.S */
1462    /*
1463     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1464     * register based on the results of the comparison.
1465     *
1466     * We load the full values with LDM, but in practice many values could
1467     * be resolved by only looking at the high word.  This could be made
1468     * faster or slower by splitting the LDM into a pair of LDRs.
1469     *
1470     * If we just wanted to set condition flags, we could do this:
1471     *  subs    ip, r0, r2
1472     *  sbcs    ip, r1, r3
1473     *  subeqs  ip, r0, r2
1474     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1475     * integer value, which we can do with 2 conditional mov/mvn instructions
1476     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1477     * us a constant 5-cycle path plus a branch at the end to the
1478     * instruction epilogue code.  The multi-compare approach below needs
1479     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1480     * in the worst case (the 64-bit values are equal).
1481     */
1482    /* cmp-long vAA, vBB, vCC */
1483    FETCH(r0, 1)                        @ r0<- CCBB
1484    mov     r9, rINST, lsr #8           @ r9<- AA
1485    and     r2, r0, #255                @ r2<- BB
1486    mov     r3, r0, lsr #8              @ r3<- CC
1487    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1488    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1489    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1490    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1491    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1492    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1493    bgt     .LOP_CMP_LONG_greater
1494    subs    r1, r0, r2                  @ r1<- r0 - r2
1495    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1496    bne     .LOP_CMP_LONG_less
1497    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1498
1499/* ------------------------------ */
1500    .balign 64
1501.L_OP_IF_EQ: /* 0x32 */
1502/* File: armv5te/OP_IF_EQ.S */
1503/* File: armv5te/bincmp.S */
1504    /*
1505     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1506     * fragment that specifies the *reverse* comparison to perform, e.g.
1507     * for "if-le" you would use "gt".
1508     *
1509     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1510     */
1511    /* if-cmp vA, vB, +CCCC */
1512    mov     r0, rINST, lsr #8           @ r0<- A+
1513    mov     r1, rINST, lsr #12          @ r1<- B
1514    and     r0, r0, #15
1515    GET_VREG(r3, r1)                    @ r3<- vB
1516    GET_VREG(r2, r0)                    @ r2<- vA
1517    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1518    cmp     r2, r3                      @ compare (vA, vB)
1519    bne  1f                      @ branch to 1 if comparison failed
1520    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1521    movs    r9, r9, asl #1              @ convert to bytes, check sign
1522    bmi     common_backwardBranch       @ yes, do periodic checks
15231:
1524#if defined(WITH_JIT)
1525    GET_JIT_PROF_TABLE(r0)
1526    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1527    b        common_testUpdateProfile
1528#else
1529    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1530    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1531    GOTO_OPCODE(ip)                     @ jump to next instruction
1532#endif
1533
1534
1535
1536/* ------------------------------ */
1537    .balign 64
1538.L_OP_IF_NE: /* 0x33 */
1539/* File: armv5te/OP_IF_NE.S */
1540/* File: armv5te/bincmp.S */
1541    /*
1542     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1543     * fragment that specifies the *reverse* comparison to perform, e.g.
1544     * for "if-le" you would use "gt".
1545     *
1546     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1547     */
1548    /* if-cmp vA, vB, +CCCC */
1549    mov     r0, rINST, lsr #8           @ r0<- A+
1550    mov     r1, rINST, lsr #12          @ r1<- B
1551    and     r0, r0, #15
1552    GET_VREG(r3, r1)                    @ r3<- vB
1553    GET_VREG(r2, r0)                    @ r2<- vA
1554    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1555    cmp     r2, r3                      @ compare (vA, vB)
1556    beq  1f                      @ branch to 1 if comparison failed
1557    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1558    movs    r9, r9, asl #1              @ convert to bytes, check sign
1559    bmi     common_backwardBranch       @ yes, do periodic checks
15601:
1561#if defined(WITH_JIT)
1562    GET_JIT_PROF_TABLE(r0)
1563    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1564    b        common_testUpdateProfile
1565#else
1566    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#endif
1570
1571
1572
1573/* ------------------------------ */
1574    .balign 64
1575.L_OP_IF_LT: /* 0x34 */
1576/* File: armv5te/OP_IF_LT.S */
1577/* File: armv5te/bincmp.S */
1578    /*
1579     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1580     * fragment that specifies the *reverse* comparison to perform, e.g.
1581     * for "if-le" you would use "gt".
1582     *
1583     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1584     */
1585    /* if-cmp vA, vB, +CCCC */
1586    mov     r0, rINST, lsr #8           @ r0<- A+
1587    mov     r1, rINST, lsr #12          @ r1<- B
1588    and     r0, r0, #15
1589    GET_VREG(r3, r1)                    @ r3<- vB
1590    GET_VREG(r2, r0)                    @ r2<- vA
1591    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1592    cmp     r2, r3                      @ compare (vA, vB)
1593    bge  1f                      @ branch to 1 if comparison failed
1594    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1595    movs    r9, r9, asl #1              @ convert to bytes, check sign
1596    bmi     common_backwardBranch       @ yes, do periodic checks
15971:
1598#if defined(WITH_JIT)
1599    GET_JIT_PROF_TABLE(r0)
1600    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1601    b        common_testUpdateProfile
1602#else
1603    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1604    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1605    GOTO_OPCODE(ip)                     @ jump to next instruction
1606#endif
1607
1608
1609
1610/* ------------------------------ */
1611    .balign 64
1612.L_OP_IF_GE: /* 0x35 */
1613/* File: armv5te/OP_IF_GE.S */
1614/* File: armv5te/bincmp.S */
1615    /*
1616     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1617     * fragment that specifies the *reverse* comparison to perform, e.g.
1618     * for "if-le" you would use "gt".
1619     *
1620     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1621     */
1622    /* if-cmp vA, vB, +CCCC */
1623    mov     r0, rINST, lsr #8           @ r0<- A+
1624    mov     r1, rINST, lsr #12          @ r1<- B
1625    and     r0, r0, #15
1626    GET_VREG(r3, r1)                    @ r3<- vB
1627    GET_VREG(r2, r0)                    @ r2<- vA
1628    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1629    cmp     r2, r3                      @ compare (vA, vB)
1630    blt  1f                      @ branch to 1 if comparison failed
1631    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1632    movs    r9, r9, asl #1              @ convert to bytes, check sign
1633    bmi     common_backwardBranch       @ yes, do periodic checks
16341:
1635#if defined(WITH_JIT)
1636    GET_JIT_PROF_TABLE(r0)
1637    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1638    b        common_testUpdateProfile
1639#else
1640    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1642    GOTO_OPCODE(ip)                     @ jump to next instruction
1643#endif
1644
1645
1646
1647/* ------------------------------ */
1648    .balign 64
1649.L_OP_IF_GT: /* 0x36 */
1650/* File: armv5te/OP_IF_GT.S */
1651/* File: armv5te/bincmp.S */
1652    /*
1653     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1654     * fragment that specifies the *reverse* comparison to perform, e.g.
1655     * for "if-le" you would use "gt".
1656     *
1657     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1658     */
1659    /* if-cmp vA, vB, +CCCC */
1660    mov     r0, rINST, lsr #8           @ r0<- A+
1661    mov     r1, rINST, lsr #12          @ r1<- B
1662    and     r0, r0, #15
1663    GET_VREG(r3, r1)                    @ r3<- vB
1664    GET_VREG(r2, r0)                    @ r2<- vA
1665    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1666    cmp     r2, r3                      @ compare (vA, vB)
1667    ble  1f                      @ branch to 1 if comparison failed
1668    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1669    movs    r9, r9, asl #1              @ convert to bytes, check sign
1670    bmi     common_backwardBranch       @ yes, do periodic checks
16711:
1672#if defined(WITH_JIT)
1673    GET_JIT_PROF_TABLE(r0)
1674    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1675    b        common_testUpdateProfile
1676#else
1677    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#endif
1681
1682
1683
1684/* ------------------------------ */
1685    .balign 64
1686.L_OP_IF_LE: /* 0x37 */
1687/* File: armv5te/OP_IF_LE.S */
1688/* File: armv5te/bincmp.S */
1689    /*
1690     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1691     * fragment that specifies the *reverse* comparison to perform, e.g.
1692     * for "if-le" you would use "gt".
1693     *
1694     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1695     */
1696    /* if-cmp vA, vB, +CCCC */
1697    mov     r0, rINST, lsr #8           @ r0<- A+
1698    mov     r1, rINST, lsr #12          @ r1<- B
1699    and     r0, r0, #15
1700    GET_VREG(r3, r1)                    @ r3<- vB
1701    GET_VREG(r2, r0)                    @ r2<- vA
1702    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1703    cmp     r2, r3                      @ compare (vA, vB)
1704    bgt  1f                      @ branch to 1 if comparison failed
1705    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1706    movs    r9, r9, asl #1              @ convert to bytes, check sign
1707    bmi     common_backwardBranch       @ yes, do periodic checks
17081:
1709#if defined(WITH_JIT)
1710    GET_JIT_PROF_TABLE(r0)
1711    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1712    b        common_testUpdateProfile
1713#else
1714    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1716    GOTO_OPCODE(ip)                     @ jump to next instruction
1717#endif
1718
1719
1720
1721/* ------------------------------ */
1722    .balign 64
1723.L_OP_IF_EQZ: /* 0x38 */
1724/* File: armv5te/OP_IF_EQZ.S */
1725/* File: armv5te/zcmp.S */
1726    /*
1727     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1728     * fragment that specifies the *reverse* comparison to perform, e.g.
1729     * for "if-le" you would use "gt".
1730     *
1731     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1732     */
1733    /* if-cmp vAA, +BBBB */
1734    mov     r0, rINST, lsr #8           @ r0<- AA
1735    GET_VREG(r2, r0)                    @ r2<- vAA
1736    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1737    cmp     r2, #0                      @ compare (vA, 0)
1738    bne  1f                      @ branch to 1 if comparison failed
1739    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1740    movs    r9, r9, asl #1              @ convert to bytes, check sign
1741    bmi     common_backwardBranch       @ backward branch, do periodic checks
17421:
1743#if defined(WITH_JIT)
1744    GET_JIT_PROF_TABLE(r0)
1745    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1746    cmp     r0,#0
1747    bne     common_updateProfile
1748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1749    GOTO_OPCODE(ip)                     @ jump to next instruction
1750#else
1751    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1752    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1753    GOTO_OPCODE(ip)                     @ jump to next instruction
1754#endif
1755
1756
1757
1758/* ------------------------------ */
1759    .balign 64
1760.L_OP_IF_NEZ: /* 0x39 */
1761/* File: armv5te/OP_IF_NEZ.S */
1762/* File: armv5te/zcmp.S */
1763    /*
1764     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1765     * fragment that specifies the *reverse* comparison to perform, e.g.
1766     * for "if-le" you would use "gt".
1767     *
1768     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1769     */
1770    /* if-cmp vAA, +BBBB */
1771    mov     r0, rINST, lsr #8           @ r0<- AA
1772    GET_VREG(r2, r0)                    @ r2<- vAA
1773    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1774    cmp     r2, #0                      @ compare (vA, 0)
1775    beq  1f                      @ branch to 1 if comparison failed
1776    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1777    movs    r9, r9, asl #1              @ convert to bytes, check sign
1778    bmi     common_backwardBranch       @ backward branch, do periodic checks
17791:
1780#if defined(WITH_JIT)
1781    GET_JIT_PROF_TABLE(r0)
1782    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1783    cmp     r0,#0
1784    bne     common_updateProfile
1785    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1786    GOTO_OPCODE(ip)                     @ jump to next instruction
1787#else
1788    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1790    GOTO_OPCODE(ip)                     @ jump to next instruction
1791#endif
1792
1793
1794
1795/* ------------------------------ */
1796    .balign 64
1797.L_OP_IF_LTZ: /* 0x3a */
1798/* File: armv5te/OP_IF_LTZ.S */
1799/* File: armv5te/zcmp.S */
1800    /*
1801     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1802     * fragment that specifies the *reverse* comparison to perform, e.g.
1803     * for "if-le" you would use "gt".
1804     *
1805     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1806     */
1807    /* if-cmp vAA, +BBBB */
1808    mov     r0, rINST, lsr #8           @ r0<- AA
1809    GET_VREG(r2, r0)                    @ r2<- vAA
1810    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1811    cmp     r2, #0                      @ compare (vA, 0)
1812    bge  1f                      @ branch to 1 if comparison failed
1813    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1814    movs    r9, r9, asl #1              @ convert to bytes, check sign
1815    bmi     common_backwardBranch       @ backward branch, do periodic checks
18161:
1817#if defined(WITH_JIT)
1818    GET_JIT_PROF_TABLE(r0)
1819    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1820    cmp     r0,#0
1821    bne     common_updateProfile
1822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1823    GOTO_OPCODE(ip)                     @ jump to next instruction
1824#else
1825    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1827    GOTO_OPCODE(ip)                     @ jump to next instruction
1828#endif
1829
1830
1831
1832/* ------------------------------ */
1833    .balign 64
1834.L_OP_IF_GEZ: /* 0x3b */
1835/* File: armv5te/OP_IF_GEZ.S */
1836/* File: armv5te/zcmp.S */
1837    /*
1838     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1839     * fragment that specifies the *reverse* comparison to perform, e.g.
1840     * for "if-le" you would use "gt".
1841     *
1842     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1843     */
1844    /* if-cmp vAA, +BBBB */
1845    mov     r0, rINST, lsr #8           @ r0<- AA
1846    GET_VREG(r2, r0)                    @ r2<- vAA
1847    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1848    cmp     r2, #0                      @ compare (vA, 0)
1849    blt  1f                      @ branch to 1 if comparison failed
1850    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1851    movs    r9, r9, asl #1              @ convert to bytes, check sign
1852    bmi     common_backwardBranch       @ backward branch, do periodic checks
18531:
1854#if defined(WITH_JIT)
1855    GET_JIT_PROF_TABLE(r0)
1856    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1857    cmp     r0,#0
1858    bne     common_updateProfile
1859    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1860    GOTO_OPCODE(ip)                     @ jump to next instruction
1861#else
1862    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1863    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1864    GOTO_OPCODE(ip)                     @ jump to next instruction
1865#endif
1866
1867
1868
1869/* ------------------------------ */
1870    .balign 64
1871.L_OP_IF_GTZ: /* 0x3c */
1872/* File: armv5te/OP_IF_GTZ.S */
1873/* File: armv5te/zcmp.S */
1874    /*
1875     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1876     * fragment that specifies the *reverse* comparison to perform, e.g.
1877     * for "if-le" you would use "gt".
1878     *
1879     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1880     */
1881    /* if-cmp vAA, +BBBB */
1882    mov     r0, rINST, lsr #8           @ r0<- AA
1883    GET_VREG(r2, r0)                    @ r2<- vAA
1884    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1885    cmp     r2, #0                      @ compare (vA, 0)
1886    ble  1f                      @ branch to 1 if comparison failed
1887    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1888    movs    r9, r9, asl #1              @ convert to bytes, check sign
1889    bmi     common_backwardBranch       @ backward branch, do periodic checks
18901:
1891#if defined(WITH_JIT)
1892    GET_JIT_PROF_TABLE(r0)
1893    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1894    cmp     r0,#0
1895    bne     common_updateProfile
1896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1897    GOTO_OPCODE(ip)                     @ jump to next instruction
1898#else
1899    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1901    GOTO_OPCODE(ip)                     @ jump to next instruction
1902#endif
1903
1904
1905
1906/* ------------------------------ */
1907    .balign 64
1908.L_OP_IF_LEZ: /* 0x3d */
1909/* File: armv5te/OP_IF_LEZ.S */
1910/* File: armv5te/zcmp.S */
1911    /*
1912     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1913     * fragment that specifies the *reverse* comparison to perform, e.g.
1914     * for "if-le" you would use "gt".
1915     *
1916     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1917     */
1918    /* if-cmp vAA, +BBBB */
1919    mov     r0, rINST, lsr #8           @ r0<- AA
1920    GET_VREG(r2, r0)                    @ r2<- vAA
1921    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1922    cmp     r2, #0                      @ compare (vA, 0)
1923    bgt  1f                      @ branch to 1 if comparison failed
1924    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1925    movs    r9, r9, asl #1              @ convert to bytes, check sign
1926    bmi     common_backwardBranch       @ backward branch, do periodic checks
19271:
1928#if defined(WITH_JIT)
1929    GET_JIT_PROF_TABLE(r0)
1930    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1931    cmp     r0,#0
1932    bne     common_updateProfile
1933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1934    GOTO_OPCODE(ip)                     @ jump to next instruction
1935#else
1936    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1938    GOTO_OPCODE(ip)                     @ jump to next instruction
1939#endif
1940
1941
1942
1943/* ------------------------------ */
1944    .balign 64
1945.L_OP_UNUSED_3E: /* 0x3e */
1946/* File: armv5te/OP_UNUSED_3E.S */
1947/* File: armv5te/unused.S */
1948    bl      common_abort
1949
1950
1951
1952/* ------------------------------ */
1953    .balign 64
1954.L_OP_UNUSED_3F: /* 0x3f */
1955/* File: armv5te/OP_UNUSED_3F.S */
1956/* File: armv5te/unused.S */
1957    bl      common_abort
1958
1959
1960
1961/* ------------------------------ */
1962    .balign 64
1963.L_OP_UNUSED_40: /* 0x40 */
1964/* File: armv5te/OP_UNUSED_40.S */
1965/* File: armv5te/unused.S */
1966    bl      common_abort
1967
1968
1969
1970/* ------------------------------ */
1971    .balign 64
1972.L_OP_UNUSED_41: /* 0x41 */
1973/* File: armv5te/OP_UNUSED_41.S */
1974/* File: armv5te/unused.S */
1975    bl      common_abort
1976
1977
1978
1979/* ------------------------------ */
1980    .balign 64
1981.L_OP_UNUSED_42: /* 0x42 */
1982/* File: armv5te/OP_UNUSED_42.S */
1983/* File: armv5te/unused.S */
1984    bl      common_abort
1985
1986
1987
1988/* ------------------------------ */
1989    .balign 64
1990.L_OP_UNUSED_43: /* 0x43 */
1991/* File: armv5te/OP_UNUSED_43.S */
1992/* File: armv5te/unused.S */
1993    bl      common_abort
1994
1995
1996
1997/* ------------------------------ */
1998    .balign 64
1999.L_OP_AGET: /* 0x44 */
2000/* File: armv5te/OP_AGET.S */
2001    /*
2002     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2003     *
2004     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2005     * instructions.  We use a pair of FETCH_Bs instead.
2006     *
2007     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2008     */
2009    /* op vAA, vBB, vCC */
2010    FETCH_B(r2, 1, 0)                   @ r2<- BB
2011    mov     r9, rINST, lsr #8           @ r9<- AA
2012    FETCH_B(r3, 1, 1)                   @ r3<- CC
2013    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2014    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2015    cmp     r0, #0                      @ null array object?
2016    beq     common_errNullObject        @ yes, bail
2017    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2018    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2019    cmp     r1, r3                      @ compare unsigned index, length
2020    bcs     common_errArrayIndex        @ index >= length, bail
2021    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2022    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2023    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2024    SET_VREG(r2, r9)                    @ vAA<- r2
2025    GOTO_OPCODE(ip)                     @ jump to next instruction
2026
2027
2028/* ------------------------------ */
2029    .balign 64
2030.L_OP_AGET_WIDE: /* 0x45 */
2031/* File: armv5te/OP_AGET_WIDE.S */
2032    /*
2033     * Array get, 64 bits.  vAA <- vBB[vCC].
2034     *
2035     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2036     */
2037    /* aget-wide vAA, vBB, vCC */
2038    FETCH(r0, 1)                        @ r0<- CCBB
2039    mov     r9, rINST, lsr #8           @ r9<- AA
2040    and     r2, r0, #255                @ r2<- BB
2041    mov     r3, r0, lsr #8              @ r3<- CC
2042    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2043    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2044    cmp     r0, #0                      @ null array object?
2045    beq     common_errNullObject        @ yes, bail
2046    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2047    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2048    cmp     r1, r3                      @ compare unsigned index, length
2049    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2050    b       common_errArrayIndex        @ index >= length, bail
2051    @ May want to swap the order of these two branches depending on how the
2052    @ branch prediction (if any) handles conditional forward branches vs.
2053    @ unconditional forward branches.
2054
2055/* ------------------------------ */
2056    .balign 64
2057.L_OP_AGET_OBJECT: /* 0x46 */
2058/* File: armv5te/OP_AGET_OBJECT.S */
2059/* File: armv5te/OP_AGET.S */
2060    /*
2061     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2062     *
2063     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2064     * instructions.  We use a pair of FETCH_Bs instead.
2065     *
2066     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2067     */
2068    /* op vAA, vBB, vCC */
2069    FETCH_B(r2, 1, 0)                   @ r2<- BB
2070    mov     r9, rINST, lsr #8           @ r9<- AA
2071    FETCH_B(r3, 1, 1)                   @ r3<- CC
2072    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2073    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2074    cmp     r0, #0                      @ null array object?
2075    beq     common_errNullObject        @ yes, bail
2076    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2077    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2078    cmp     r1, r3                      @ compare unsigned index, length
2079    bcs     common_errArrayIndex        @ index >= length, bail
2080    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2081    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2082    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2083    SET_VREG(r2, r9)                    @ vAA<- r2
2084    GOTO_OPCODE(ip)                     @ jump to next instruction
2085
2086
2087
2088/* ------------------------------ */
2089    .balign 64
2090.L_OP_AGET_BOOLEAN: /* 0x47 */
2091/* File: armv5te/OP_AGET_BOOLEAN.S */
2092/* File: armv5te/OP_AGET.S */
2093    /*
2094     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2095     *
2096     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2097     * instructions.  We use a pair of FETCH_Bs instead.
2098     *
2099     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2100     */
2101    /* op vAA, vBB, vCC */
2102    FETCH_B(r2, 1, 0)                   @ r2<- BB
2103    mov     r9, rINST, lsr #8           @ r9<- AA
2104    FETCH_B(r3, 1, 1)                   @ r3<- CC
2105    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2106    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2107    cmp     r0, #0                      @ null array object?
2108    beq     common_errNullObject        @ yes, bail
2109    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2110    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2111    cmp     r1, r3                      @ compare unsigned index, length
2112    bcs     common_errArrayIndex        @ index >= length, bail
2113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2114    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2116    SET_VREG(r2, r9)                    @ vAA<- r2
2117    GOTO_OPCODE(ip)                     @ jump to next instruction
2118
2119
2120
2121/* ------------------------------ */
2122    .balign 64
2123.L_OP_AGET_BYTE: /* 0x48 */
2124/* File: armv5te/OP_AGET_BYTE.S */
2125/* File: armv5te/OP_AGET.S */
2126    /*
2127     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2128     *
2129     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2130     * instructions.  We use a pair of FETCH_Bs instead.
2131     *
2132     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2133     */
2134    /* op vAA, vBB, vCC */
2135    FETCH_B(r2, 1, 0)                   @ r2<- BB
2136    mov     r9, rINST, lsr #8           @ r9<- AA
2137    FETCH_B(r3, 1, 1)                   @ r3<- CC
2138    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2139    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2140    cmp     r0, #0                      @ null array object?
2141    beq     common_errNullObject        @ yes, bail
2142    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2143    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2144    cmp     r1, r3                      @ compare unsigned index, length
2145    bcs     common_errArrayIndex        @ index >= length, bail
2146    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2147    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2148    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2149    SET_VREG(r2, r9)                    @ vAA<- r2
2150    GOTO_OPCODE(ip)                     @ jump to next instruction
2151
2152
2153
2154/* ------------------------------ */
2155    .balign 64
2156.L_OP_AGET_CHAR: /* 0x49 */
2157/* File: armv5te/OP_AGET_CHAR.S */
2158/* File: armv5te/OP_AGET.S */
2159    /*
2160     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2161     *
2162     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2163     * instructions.  We use a pair of FETCH_Bs instead.
2164     *
2165     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2166     */
2167    /* op vAA, vBB, vCC */
2168    FETCH_B(r2, 1, 0)                   @ r2<- BB
2169    mov     r9, rINST, lsr #8           @ r9<- AA
2170    FETCH_B(r3, 1, 1)                   @ r3<- CC
2171    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2172    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2173    cmp     r0, #0                      @ null array object?
2174    beq     common_errNullObject        @ yes, bail
2175    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2176    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2177    cmp     r1, r3                      @ compare unsigned index, length
2178    bcs     common_errArrayIndex        @ index >= length, bail
2179    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2180    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2182    SET_VREG(r2, r9)                    @ vAA<- r2
2183    GOTO_OPCODE(ip)                     @ jump to next instruction
2184
2185
2186
2187/* ------------------------------ */
2188    .balign 64
2189.L_OP_AGET_SHORT: /* 0x4a */
2190/* File: armv5te/OP_AGET_SHORT.S */
2191/* File: armv5te/OP_AGET.S */
2192    /*
2193     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2194     *
2195     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2196     * instructions.  We use a pair of FETCH_Bs instead.
2197     *
2198     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2199     */
2200    /* op vAA, vBB, vCC */
2201    FETCH_B(r2, 1, 0)                   @ r2<- BB
2202    mov     r9, rINST, lsr #8           @ r9<- AA
2203    FETCH_B(r3, 1, 1)                   @ r3<- CC
2204    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2205    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2206    cmp     r0, #0                      @ null array object?
2207    beq     common_errNullObject        @ yes, bail
2208    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2209    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2210    cmp     r1, r3                      @ compare unsigned index, length
2211    bcs     common_errArrayIndex        @ index >= length, bail
2212    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2213    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2214    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2215    SET_VREG(r2, r9)                    @ vAA<- r2
2216    GOTO_OPCODE(ip)                     @ jump to next instruction
2217
2218
2219
2220/* ------------------------------ */
2221    .balign 64
2222.L_OP_APUT: /* 0x4b */
2223/* File: armv5te/OP_APUT.S */
2224    /*
2225     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2226     *
2227     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2228     * instructions.  We use a pair of FETCH_Bs instead.
2229     *
2230     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2231     */
2232    /* op vAA, vBB, vCC */
2233    FETCH_B(r2, 1, 0)                   @ r2<- BB
2234    mov     r9, rINST, lsr #8           @ r9<- AA
2235    FETCH_B(r3, 1, 1)                   @ r3<- CC
2236    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2237    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2238    cmp     r0, #0                      @ null array object?
2239    beq     common_errNullObject        @ yes, bail
2240    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2241    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2242    cmp     r1, r3                      @ compare unsigned index, length
2243    bcs     common_errArrayIndex        @ index >= length, bail
2244    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2245    GET_VREG(r2, r9)                    @ r2<- vAA
2246    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2247    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2248    GOTO_OPCODE(ip)                     @ jump to next instruction
2249
2250
2251/* ------------------------------ */
2252    .balign 64
2253.L_OP_APUT_WIDE: /* 0x4c */
2254/* File: armv5te/OP_APUT_WIDE.S */
2255    /*
2256     * Array put, 64 bits.  vBB[vCC] <- vAA.
2257     *
2258     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2259     */
2260    /* aput-wide vAA, vBB, vCC */
2261    FETCH(r0, 1)                        @ r0<- CCBB
2262    mov     r9, rINST, lsr #8           @ r9<- AA
2263    and     r2, r0, #255                @ r2<- BB
2264    mov     r3, r0, lsr #8              @ r3<- CC
2265    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2266    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2267    cmp     r0, #0                      @ null array object?
2268    beq     common_errNullObject        @ yes, bail
2269    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2270    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2271    cmp     r1, r3                      @ compare unsigned index, length
2272    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2273    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2274    b       common_errArrayIndex        @ index >= length, bail
2275    @ May want to swap the order of these two branches depending on how the
2276    @ branch prediction (if any) handles conditional forward branches vs.
2277    @ unconditional forward branches.
2278
2279/* ------------------------------ */
2280    .balign 64
2281.L_OP_APUT_OBJECT: /* 0x4d */
2282/* File: armv5te/OP_APUT_OBJECT.S */
2283    /*
2284     * Store an object into an array.  vBB[vCC] <- vAA.
2285     *
2286     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2287     * instructions.  We use a pair of FETCH_Bs instead.
2288     */
2289    /* op vAA, vBB, vCC */
2290    FETCH(r0, 1)                        @ r0<- CCBB
2291    mov     r9, rINST, lsr #8           @ r9<- AA
2292    and     r2, r0, #255                @ r2<- BB
2293    mov     r3, r0, lsr #8              @ r3<- CC
2294    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2295    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2296    cmp     r1, #0                      @ null array object?
2297    GET_VREG(r9, r9)                    @ r9<- vAA
2298    beq     common_errNullObject        @ yes, bail
2299    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2300    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2301    cmp     r0, r3                      @ compare unsigned index, length
2302    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2303    b       common_errArrayIndex        @ index >= length, bail
2304
2305
2306/* ------------------------------ */
2307    .balign 64
2308.L_OP_APUT_BOOLEAN: /* 0x4e */
2309/* File: armv5te/OP_APUT_BOOLEAN.S */
2310/* File: armv5te/OP_APUT.S */
2311    /*
2312     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2313     *
2314     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2315     * instructions.  We use a pair of FETCH_Bs instead.
2316     *
2317     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2318     */
2319    /* op vAA, vBB, vCC */
2320    FETCH_B(r2, 1, 0)                   @ r2<- BB
2321    mov     r9, rINST, lsr #8           @ r9<- AA
2322    FETCH_B(r3, 1, 1)                   @ r3<- CC
2323    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2324    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2325    cmp     r0, #0                      @ null array object?
2326    beq     common_errNullObject        @ yes, bail
2327    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2328    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2329    cmp     r1, r3                      @ compare unsigned index, length
2330    bcs     common_errArrayIndex        @ index >= length, bail
2331    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2332    GET_VREG(r2, r9)                    @ r2<- vAA
2333    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2334    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2335    GOTO_OPCODE(ip)                     @ jump to next instruction
2336
2337
2338
2339/* ------------------------------ */
2340    .balign 64
2341.L_OP_APUT_BYTE: /* 0x4f */
2342/* File: armv5te/OP_APUT_BYTE.S */
2343/* File: armv5te/OP_APUT.S */
2344    /*
2345     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2346     *
2347     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2348     * instructions.  We use a pair of FETCH_Bs instead.
2349     *
2350     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2351     */
2352    /* op vAA, vBB, vCC */
2353    FETCH_B(r2, 1, 0)                   @ r2<- BB
2354    mov     r9, rINST, lsr #8           @ r9<- AA
2355    FETCH_B(r3, 1, 1)                   @ r3<- CC
2356    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2357    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2358    cmp     r0, #0                      @ null array object?
2359    beq     common_errNullObject        @ yes, bail
2360    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2361    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2362    cmp     r1, r3                      @ compare unsigned index, length
2363    bcs     common_errArrayIndex        @ index >= length, bail
2364    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2365    GET_VREG(r2, r9)                    @ r2<- vAA
2366    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2367    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2368    GOTO_OPCODE(ip)                     @ jump to next instruction
2369
2370
2371
2372/* ------------------------------ */
2373    .balign 64
2374.L_OP_APUT_CHAR: /* 0x50 */
2375/* File: armv5te/OP_APUT_CHAR.S */
2376/* File: armv5te/OP_APUT.S */
2377    /*
2378     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2379     *
2380     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2381     * instructions.  We use a pair of FETCH_Bs instead.
2382     *
2383     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2384     */
2385    /* op vAA, vBB, vCC */
2386    FETCH_B(r2, 1, 0)                   @ r2<- BB
2387    mov     r9, rINST, lsr #8           @ r9<- AA
2388    FETCH_B(r3, 1, 1)                   @ r3<- CC
2389    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2390    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2391    cmp     r0, #0                      @ null array object?
2392    beq     common_errNullObject        @ yes, bail
2393    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2394    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2395    cmp     r1, r3                      @ compare unsigned index, length
2396    bcs     common_errArrayIndex        @ index >= length, bail
2397    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2398    GET_VREG(r2, r9)                    @ r2<- vAA
2399    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2400    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2401    GOTO_OPCODE(ip)                     @ jump to next instruction
2402
2403
2404
2405/* ------------------------------ */
2406    .balign 64
2407.L_OP_APUT_SHORT: /* 0x51 */
2408/* File: armv5te/OP_APUT_SHORT.S */
2409/* File: armv5te/OP_APUT.S */
2410    /*
2411     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2412     *
2413     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2414     * instructions.  We use a pair of FETCH_Bs instead.
2415     *
2416     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2417     */
2418    /* op vAA, vBB, vCC */
2419    FETCH_B(r2, 1, 0)                   @ r2<- BB
2420    mov     r9, rINST, lsr #8           @ r9<- AA
2421    FETCH_B(r3, 1, 1)                   @ r3<- CC
2422    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2423    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2424    cmp     r0, #0                      @ null array object?
2425    beq     common_errNullObject        @ yes, bail
2426    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2427    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2428    cmp     r1, r3                      @ compare unsigned index, length
2429    bcs     common_errArrayIndex        @ index >= length, bail
2430    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2431    GET_VREG(r2, r9)                    @ r2<- vAA
2432    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2433    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2434    GOTO_OPCODE(ip)                     @ jump to next instruction
2435
2436
2437
2438/* ------------------------------ */
2439    .balign 64
2440.L_OP_IGET: /* 0x52 */
2441/* File: armv5te/OP_IGET.S */
2442    /*
2443     * General 32-bit instance field get.
2444     *
2445     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2446     */
2447    /* op vA, vB, field@CCCC */
2448    mov     r0, rINST, lsr #12          @ r0<- B
2449    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2450    FETCH(r1, 1)                        @ r1<- field ref CCCC
2451    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2452    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2453    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2454    cmp     r0, #0                      @ is resolved entry null?
2455    bne     .LOP_IGET_finish          @ no, already resolved
24568:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2457    EXPORT_PC()                         @ resolve() could throw
2458    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2459    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2460    cmp     r0, #0
2461    bne     .LOP_IGET_finish
2462    b       common_exceptionThrown
2463
2464/* ------------------------------ */
2465    .balign 64
2466.L_OP_IGET_WIDE: /* 0x53 */
2467/* File: armv5te/OP_IGET_WIDE.S */
2468    /*
2469     * Wide 32-bit instance field get.
2470     */
2471    /* iget-wide vA, vB, field@CCCC */
2472    mov     r0, rINST, lsr #12          @ r0<- B
2473    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2474    FETCH(r1, 1)                        @ r1<- field ref CCCC
2475    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2476    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2477    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2478    cmp     r0, #0                      @ is resolved entry null?
2479    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24808:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2481    EXPORT_PC()                         @ resolve() could throw
2482    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2483    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2484    cmp     r0, #0
2485    bne     .LOP_IGET_WIDE_finish
2486    b       common_exceptionThrown
2487
2488/* ------------------------------ */
2489    .balign 64
2490.L_OP_IGET_OBJECT: /* 0x54 */
2491/* File: armv5te/OP_IGET_OBJECT.S */
2492/* File: armv5te/OP_IGET.S */
2493    /*
2494     * General 32-bit instance field get.
2495     *
2496     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2497     */
2498    /* op vA, vB, field@CCCC */
2499    mov     r0, rINST, lsr #12          @ r0<- B
2500    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2501    FETCH(r1, 1)                        @ r1<- field ref CCCC
2502    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2503    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2504    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2505    cmp     r0, #0                      @ is resolved entry null?
2506    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2508    EXPORT_PC()                         @ resolve() could throw
2509    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2510    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2511    cmp     r0, #0
2512    bne     .LOP_IGET_OBJECT_finish
2513    b       common_exceptionThrown
2514
2515
2516/* ------------------------------ */
2517    .balign 64
2518.L_OP_IGET_BOOLEAN: /* 0x55 */
2519/* File: armv5te/OP_IGET_BOOLEAN.S */
2520@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2521/* File: armv5te/OP_IGET.S */
2522    /*
2523     * General 32-bit instance field get.
2524     *
2525     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2526     */
2527    /* op vA, vB, field@CCCC */
2528    mov     r0, rINST, lsr #12          @ r0<- B
2529    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2530    FETCH(r1, 1)                        @ r1<- field ref CCCC
2531    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2532    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2533    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2534    cmp     r0, #0                      @ is resolved entry null?
2535    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25368:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2537    EXPORT_PC()                         @ resolve() could throw
2538    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2539    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2540    cmp     r0, #0
2541    bne     .LOP_IGET_BOOLEAN_finish
2542    b       common_exceptionThrown
2543
2544
2545/* ------------------------------ */
2546    .balign 64
2547.L_OP_IGET_BYTE: /* 0x56 */
2548/* File: armv5te/OP_IGET_BYTE.S */
2549@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2550/* File: armv5te/OP_IGET.S */
2551    /*
2552     * General 32-bit instance field get.
2553     *
2554     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2555     */
2556    /* op vA, vB, field@CCCC */
2557    mov     r0, rINST, lsr #12          @ r0<- B
2558    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2559    FETCH(r1, 1)                        @ r1<- field ref CCCC
2560    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2561    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2562    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2563    cmp     r0, #0                      @ is resolved entry null?
2564    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25658:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2566    EXPORT_PC()                         @ resolve() could throw
2567    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2568    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2569    cmp     r0, #0
2570    bne     .LOP_IGET_BYTE_finish
2571    b       common_exceptionThrown
2572
2573
2574/* ------------------------------ */
2575    .balign 64
2576.L_OP_IGET_CHAR: /* 0x57 */
2577/* File: armv5te/OP_IGET_CHAR.S */
2578@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2579/* File: armv5te/OP_IGET.S */
2580    /*
2581     * General 32-bit instance field get.
2582     *
2583     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2584     */
2585    /* op vA, vB, field@CCCC */
2586    mov     r0, rINST, lsr #12          @ r0<- B
2587    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2588    FETCH(r1, 1)                        @ r1<- field ref CCCC
2589    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2590    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2591    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2592    cmp     r0, #0                      @ is resolved entry null?
2593    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2595    EXPORT_PC()                         @ resolve() could throw
2596    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2597    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2598    cmp     r0, #0
2599    bne     .LOP_IGET_CHAR_finish
2600    b       common_exceptionThrown
2601
2602
2603/* ------------------------------ */
2604    .balign 64
2605.L_OP_IGET_SHORT: /* 0x58 */
2606/* File: armv5te/OP_IGET_SHORT.S */
2607@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2608/* File: armv5te/OP_IGET.S */
2609    /*
2610     * General 32-bit instance field get.
2611     *
2612     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2613     */
2614    /* op vA, vB, field@CCCC */
2615    mov     r0, rINST, lsr #12          @ r0<- B
2616    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2617    FETCH(r1, 1)                        @ r1<- field ref CCCC
2618    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2619    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2620    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2621    cmp     r0, #0                      @ is resolved entry null?
2622    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26238:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2624    EXPORT_PC()                         @ resolve() could throw
2625    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2626    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2627    cmp     r0, #0
2628    bne     .LOP_IGET_SHORT_finish
2629    b       common_exceptionThrown
2630
2631
2632/* ------------------------------ */
2633    .balign 64
2634.L_OP_IPUT: /* 0x59 */
2635/* File: armv5te/OP_IPUT.S */
2636    /*
2637     * General 32-bit instance field put.
2638     *
2639     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2640     */
2641    /* op vA, vB, field@CCCC */
2642    mov     r0, rINST, lsr #12          @ r0<- B
2643    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2644    FETCH(r1, 1)                        @ r1<- field ref CCCC
2645    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2646    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2647    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2648    cmp     r0, #0                      @ is resolved entry null?
2649    bne     .LOP_IPUT_finish          @ no, already resolved
26508:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2651    EXPORT_PC()                         @ resolve() could throw
2652    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2653    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2654    cmp     r0, #0                      @ success?
2655    bne     .LOP_IPUT_finish          @ yes, finish up
2656    b       common_exceptionThrown
2657
2658/* ------------------------------ */
2659    .balign 64
2660.L_OP_IPUT_WIDE: /* 0x5a */
2661/* File: armv5te/OP_IPUT_WIDE.S */
2662    /* iput-wide vA, vB, field@CCCC */
2663    mov     r0, rINST, lsr #12          @ r0<- B
2664    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2665    FETCH(r1, 1)                        @ r1<- field ref CCCC
2666    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2667    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2668    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2669    cmp     r0, #0                      @ is resolved entry null?
2670    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26718:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2672    EXPORT_PC()                         @ resolve() could throw
2673    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2674    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2675    cmp     r0, #0                      @ success?
2676    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2677    b       common_exceptionThrown
2678
2679/* ------------------------------ */
2680    .balign 64
2681.L_OP_IPUT_OBJECT: /* 0x5b */
2682/* File: armv5te/OP_IPUT_OBJECT.S */
2683/* File: armv5te/OP_IPUT.S */
2684    /*
2685     * General 32-bit instance field put.
2686     *
2687     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2688     */
2689    /* op vA, vB, field@CCCC */
2690    mov     r0, rINST, lsr #12          @ r0<- B
2691    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2692    FETCH(r1, 1)                        @ r1<- field ref CCCC
2693    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2694    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2695    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2696    cmp     r0, #0                      @ is resolved entry null?
2697    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26988:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2699    EXPORT_PC()                         @ resolve() could throw
2700    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2701    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2702    cmp     r0, #0                      @ success?
2703    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2704    b       common_exceptionThrown
2705
2706
2707/* ------------------------------ */
2708    .balign 64
2709.L_OP_IPUT_BOOLEAN: /* 0x5c */
2710/* File: armv5te/OP_IPUT_BOOLEAN.S */
2711@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2712/* File: armv5te/OP_IPUT.S */
2713    /*
2714     * General 32-bit instance field put.
2715     *
2716     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2717     */
2718    /* op vA, vB, field@CCCC */
2719    mov     r0, rINST, lsr #12          @ r0<- B
2720    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2721    FETCH(r1, 1)                        @ r1<- field ref CCCC
2722    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2723    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2724    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2725    cmp     r0, #0                      @ is resolved entry null?
2726    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27278:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2728    EXPORT_PC()                         @ resolve() could throw
2729    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2730    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2731    cmp     r0, #0                      @ success?
2732    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2733    b       common_exceptionThrown
2734
2735
2736/* ------------------------------ */
2737    .balign 64
2738.L_OP_IPUT_BYTE: /* 0x5d */
2739/* File: armv5te/OP_IPUT_BYTE.S */
2740@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2741/* File: armv5te/OP_IPUT.S */
2742    /*
2743     * General 32-bit instance field put.
2744     *
2745     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2746     */
2747    /* op vA, vB, field@CCCC */
2748    mov     r0, rINST, lsr #12          @ r0<- B
2749    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2750    FETCH(r1, 1)                        @ r1<- field ref CCCC
2751    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2752    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2753    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2754    cmp     r0, #0                      @ is resolved entry null?
2755    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27568:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2757    EXPORT_PC()                         @ resolve() could throw
2758    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2759    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2760    cmp     r0, #0                      @ success?
2761    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2762    b       common_exceptionThrown
2763
2764
2765/* ------------------------------ */
2766    .balign 64
2767.L_OP_IPUT_CHAR: /* 0x5e */
2768/* File: armv5te/OP_IPUT_CHAR.S */
2769@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2770/* File: armv5te/OP_IPUT.S */
2771    /*
2772     * General 32-bit instance field put.
2773     *
2774     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2775     */
2776    /* op vA, vB, field@CCCC */
2777    mov     r0, rINST, lsr #12          @ r0<- B
2778    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2779    FETCH(r1, 1)                        @ r1<- field ref CCCC
2780    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2781    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2782    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2783    cmp     r0, #0                      @ is resolved entry null?
2784    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27858:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2786    EXPORT_PC()                         @ resolve() could throw
2787    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2788    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2789    cmp     r0, #0                      @ success?
2790    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2791    b       common_exceptionThrown
2792
2793
2794/* ------------------------------ */
2795    .balign 64
2796.L_OP_IPUT_SHORT: /* 0x5f */
2797/* File: armv5te/OP_IPUT_SHORT.S */
2798@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2799/* File: armv5te/OP_IPUT.S */
2800    /*
2801     * General 32-bit instance field put.
2802     *
2803     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2804     */
2805    /* op vA, vB, field@CCCC */
2806    mov     r0, rINST, lsr #12          @ r0<- B
2807    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2808    FETCH(r1, 1)                        @ r1<- field ref CCCC
2809    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2810    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2811    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2812    cmp     r0, #0                      @ is resolved entry null?
2813    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28148:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2815    EXPORT_PC()                         @ resolve() could throw
2816    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2817    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2818    cmp     r0, #0                      @ success?
2819    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2820    b       common_exceptionThrown
2821
2822
2823/* ------------------------------ */
2824    .balign 64
2825.L_OP_SGET: /* 0x60 */
2826/* File: armv5te/OP_SGET.S */
2827    /*
2828     * General 32-bit SGET handler.
2829     *
2830     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2831     */
2832    /* op vAA, field@BBBB */
2833    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2834    FETCH(r1, 1)                        @ r1<- field ref BBBB
2835    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2836    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2837    cmp     r0, #0                      @ is resolved entry null?
2838    beq     .LOP_SGET_resolve         @ yes, do resolve
2839.LOP_SGET_finish: @ field ptr in r0
2840    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2841    mov     r2, rINST, lsr #8           @ r2<- AA
2842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2843    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2844    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2845    GOTO_OPCODE(ip)                     @ jump to next instruction
2846
2847/* ------------------------------ */
2848    .balign 64
2849.L_OP_SGET_WIDE: /* 0x61 */
2850/* File: armv5te/OP_SGET_WIDE.S */
2851    /*
2852     * 64-bit SGET handler.
2853     */
2854    /* sget-wide vAA, field@BBBB */
2855    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2856    FETCH(r1, 1)                        @ r1<- field ref BBBB
2857    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2858    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2859    cmp     r0, #0                      @ is resolved entry null?
2860    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2861.LOP_SGET_WIDE_finish:
2862    mov     r1, rINST, lsr #8           @ r1<- AA
2863    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2864    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2865    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2866    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2867    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2868    GOTO_OPCODE(ip)                     @ jump to next instruction
2869
2870/* ------------------------------ */
2871    .balign 64
2872.L_OP_SGET_OBJECT: /* 0x62 */
2873/* File: armv5te/OP_SGET_OBJECT.S */
2874/* File: armv5te/OP_SGET.S */
2875    /*
2876     * General 32-bit SGET handler.
2877     *
2878     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2879     */
2880    /* op vAA, field@BBBB */
2881    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2882    FETCH(r1, 1)                        @ r1<- field ref BBBB
2883    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2885    cmp     r0, #0                      @ is resolved entry null?
2886    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2887.LOP_SGET_OBJECT_finish: @ field ptr in r0
2888    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2889    mov     r2, rINST, lsr #8           @ r2<- AA
2890    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2891    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2892    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2893    GOTO_OPCODE(ip)                     @ jump to next instruction
2894
2895
2896/* ------------------------------ */
2897    .balign 64
2898.L_OP_SGET_BOOLEAN: /* 0x63 */
2899/* File: armv5te/OP_SGET_BOOLEAN.S */
2900/* File: armv5te/OP_SGET.S */
2901    /*
2902     * General 32-bit SGET handler.
2903     *
2904     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2905     */
2906    /* op vAA, field@BBBB */
2907    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2908    FETCH(r1, 1)                        @ r1<- field ref BBBB
2909    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2910    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2911    cmp     r0, #0                      @ is resolved entry null?
2912    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2913.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2914    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2915    mov     r2, rINST, lsr #8           @ r2<- AA
2916    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2917    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2918    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2919    GOTO_OPCODE(ip)                     @ jump to next instruction
2920
2921
2922/* ------------------------------ */
2923    .balign 64
2924.L_OP_SGET_BYTE: /* 0x64 */
2925/* File: armv5te/OP_SGET_BYTE.S */
2926/* File: armv5te/OP_SGET.S */
2927    /*
2928     * General 32-bit SGET handler.
2929     *
2930     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2931     */
2932    /* op vAA, field@BBBB */
2933    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2934    FETCH(r1, 1)                        @ r1<- field ref BBBB
2935    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2936    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2937    cmp     r0, #0                      @ is resolved entry null?
2938    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2939.LOP_SGET_BYTE_finish: @ field ptr in r0
2940    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2941    mov     r2, rINST, lsr #8           @ r2<- AA
2942    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2943    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2944    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2945    GOTO_OPCODE(ip)                     @ jump to next instruction
2946
2947
2948/* ------------------------------ */
2949    .balign 64
2950.L_OP_SGET_CHAR: /* 0x65 */
2951/* File: armv5te/OP_SGET_CHAR.S */
2952/* File: armv5te/OP_SGET.S */
2953    /*
2954     * General 32-bit SGET handler.
2955     *
2956     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2957     */
2958    /* op vAA, field@BBBB */
2959    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2960    FETCH(r1, 1)                        @ r1<- field ref BBBB
2961    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2962    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2963    cmp     r0, #0                      @ is resolved entry null?
2964    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2965.LOP_SGET_CHAR_finish: @ field ptr in r0
2966    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2967    mov     r2, rINST, lsr #8           @ r2<- AA
2968    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2969    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2970    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2971    GOTO_OPCODE(ip)                     @ jump to next instruction
2972
2973
2974/* ------------------------------ */
2975    .balign 64
2976.L_OP_SGET_SHORT: /* 0x66 */
2977/* File: armv5te/OP_SGET_SHORT.S */
2978/* File: armv5te/OP_SGET.S */
2979    /*
2980     * General 32-bit SGET handler.
2981     *
2982     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2983     */
2984    /* op vAA, field@BBBB */
2985    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2986    FETCH(r1, 1)                        @ r1<- field ref BBBB
2987    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2988    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2989    cmp     r0, #0                      @ is resolved entry null?
2990    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2991.LOP_SGET_SHORT_finish: @ field ptr in r0
2992    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2993    mov     r2, rINST, lsr #8           @ r2<- AA
2994    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2995    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2996    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2997    GOTO_OPCODE(ip)                     @ jump to next instruction
2998
2999
3000/* ------------------------------ */
3001    .balign 64
3002.L_OP_SPUT: /* 0x67 */
3003/* File: armv5te/OP_SPUT.S */
3004    /*
3005     * General 32-bit SPUT handler.
3006     *
3007     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3008     */
3009    /* op vAA, field@BBBB */
3010    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3011    FETCH(r1, 1)                        @ r1<- field ref BBBB
3012    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3013    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3014    cmp     r0, #0                      @ is resolved entry null?
3015    beq     .LOP_SPUT_resolve         @ yes, do resolve
3016.LOP_SPUT_finish:   @ field ptr in r0
3017    mov     r2, rINST, lsr #8           @ r2<- AA
3018    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3019    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3020    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3021    str     r1, [r0, #offStaticField_value] @ field<- vAA
3022    GOTO_OPCODE(ip)                     @ jump to next instruction
3023
3024/* ------------------------------ */
3025    .balign 64
3026.L_OP_SPUT_WIDE: /* 0x68 */
3027/* File: armv5te/OP_SPUT_WIDE.S */
3028    /*
3029     * 64-bit SPUT handler.
3030     */
3031    /* sput-wide vAA, field@BBBB */
3032    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3033    FETCH(r1, 1)                        @ r1<- field ref BBBB
3034    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3035    mov     r9, rINST, lsr #8           @ r9<- AA
3036    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3037    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3038    cmp     r0, #0                      @ is resolved entry null?
3039    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3040.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3041    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3042    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3043    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3044    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3045    GOTO_OPCODE(ip)                     @ jump to next instruction
3046
3047/* ------------------------------ */
3048    .balign 64
3049.L_OP_SPUT_OBJECT: /* 0x69 */
3050/* File: armv5te/OP_SPUT_OBJECT.S */
3051/* File: armv5te/OP_SPUT.S */
3052    /*
3053     * General 32-bit SPUT handler.
3054     *
3055     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3056     */
3057    /* op vAA, field@BBBB */
3058    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3059    FETCH(r1, 1)                        @ r1<- field ref BBBB
3060    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3061    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3062    cmp     r0, #0                      @ is resolved entry null?
3063    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3064.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3065    mov     r2, rINST, lsr #8           @ r2<- AA
3066    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3067    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3068    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3069    str     r1, [r0, #offStaticField_value] @ field<- vAA
3070    GOTO_OPCODE(ip)                     @ jump to next instruction
3071
3072
3073/* ------------------------------ */
3074    .balign 64
3075.L_OP_SPUT_BOOLEAN: /* 0x6a */
3076/* File: armv5te/OP_SPUT_BOOLEAN.S */
3077/* File: armv5te/OP_SPUT.S */
3078    /*
3079     * General 32-bit SPUT handler.
3080     *
3081     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3082     */
3083    /* op vAA, field@BBBB */
3084    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3085    FETCH(r1, 1)                        @ r1<- field ref BBBB
3086    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3087    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3088    cmp     r0, #0                      @ is resolved entry null?
3089    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3090.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3091    mov     r2, rINST, lsr #8           @ r2<- AA
3092    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3093    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3094    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3095    str     r1, [r0, #offStaticField_value] @ field<- vAA
3096    GOTO_OPCODE(ip)                     @ jump to next instruction
3097
3098
3099/* ------------------------------ */
3100    .balign 64
3101.L_OP_SPUT_BYTE: /* 0x6b */
3102/* File: armv5te/OP_SPUT_BYTE.S */
3103/* File: armv5te/OP_SPUT.S */
3104    /*
3105     * General 32-bit SPUT handler.
3106     *
3107     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3108     */
3109    /* op vAA, field@BBBB */
3110    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3111    FETCH(r1, 1)                        @ r1<- field ref BBBB
3112    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3113    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3114    cmp     r0, #0                      @ is resolved entry null?
3115    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3116.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3117    mov     r2, rINST, lsr #8           @ r2<- AA
3118    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3119    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3120    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3121    str     r1, [r0, #offStaticField_value] @ field<- vAA
3122    GOTO_OPCODE(ip)                     @ jump to next instruction
3123
3124
3125/* ------------------------------ */
3126    .balign 64
3127.L_OP_SPUT_CHAR: /* 0x6c */
3128/* File: armv5te/OP_SPUT_CHAR.S */
3129/* File: armv5te/OP_SPUT.S */
3130    /*
3131     * General 32-bit SPUT handler.
3132     *
3133     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3134     */
3135    /* op vAA, field@BBBB */
3136    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3137    FETCH(r1, 1)                        @ r1<- field ref BBBB
3138    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3139    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3140    cmp     r0, #0                      @ is resolved entry null?
3141    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3142.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3143    mov     r2, rINST, lsr #8           @ r2<- AA
3144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3145    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3147    str     r1, [r0, #offStaticField_value] @ field<- vAA
3148    GOTO_OPCODE(ip)                     @ jump to next instruction
3149
3150
3151/* ------------------------------ */
3152    .balign 64
3153.L_OP_SPUT_SHORT: /* 0x6d */
3154/* File: armv5te/OP_SPUT_SHORT.S */
3155/* File: armv5te/OP_SPUT.S */
3156    /*
3157     * General 32-bit SPUT handler.
3158     *
3159     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3160     */
3161    /* op vAA, field@BBBB */
3162    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3163    FETCH(r1, 1)                        @ r1<- field ref BBBB
3164    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3165    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3166    cmp     r0, #0                      @ is resolved entry null?
3167    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3168.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3169    mov     r2, rINST, lsr #8           @ r2<- AA
3170    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3171    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3172    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3173    str     r1, [r0, #offStaticField_value] @ field<- vAA
3174    GOTO_OPCODE(ip)                     @ jump to next instruction
3175
3176
3177/* ------------------------------ */
3178    .balign 64
3179.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3180/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3181    /*
3182     * Handle a virtual method call.
3183     *
3184     * for: invoke-virtual, invoke-virtual/range
3185     */
3186    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3187    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3188    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3189    FETCH(r1, 1)                        @ r1<- BBBB
3190    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3191    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3192    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3193    .if     (!0)
3194    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3195    .endif
3196    cmp     r0, #0                      @ already resolved?
3197    EXPORT_PC()                         @ must export for invoke
3198    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3199    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3200    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3201    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3202    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3203    cmp     r0, #0                      @ got null?
3204    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3205    b       common_exceptionThrown      @ yes, handle exception
3206
3207/* ------------------------------ */
3208    .balign 64
3209.L_OP_INVOKE_SUPER: /* 0x6f */
3210/* File: armv5te/OP_INVOKE_SUPER.S */
3211    /*
3212     * Handle a "super" method call.
3213     *
3214     * for: invoke-super, invoke-super/range
3215     */
3216    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3217    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3218    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3219    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3220    .if     (!0)
3221    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3222    .endif
3223    FETCH(r1, 1)                        @ r1<- BBBB
3224    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3225    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3226    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3227    cmp     r2, #0                      @ null "this"?
3228    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3229    beq     common_errNullObject        @ null "this", throw exception
3230    cmp     r0, #0                      @ already resolved?
3231    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3232    EXPORT_PC()                         @ must export for invoke
3233    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3234    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3235
3236/* ------------------------------ */
3237    .balign 64
3238.L_OP_INVOKE_DIRECT: /* 0x70 */
3239/* File: armv5te/OP_INVOKE_DIRECT.S */
3240    /*
3241     * Handle a direct method call.
3242     *
3243     * (We could defer the "is 'this' pointer null" test to the common
3244     * method invocation code, and use a flag to indicate that static
3245     * calls don't count.  If we do this as part of copying the arguments
3246     * out we could avoiding loading the first arg twice.)
3247     *
3248     * for: invoke-direct, invoke-direct/range
3249     */
3250    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3251    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3252    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3253    FETCH(r1, 1)                        @ r1<- BBBB
3254    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3255    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3256    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3257    .if     (!0)
3258    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3259    .endif
3260    cmp     r0, #0                      @ already resolved?
3261    EXPORT_PC()                         @ must export for invoke
3262    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3263    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3264.LOP_INVOKE_DIRECT_finish:
3265    cmp     r2, #0                      @ null "this" ref?
3266    bne     common_invokeMethodNoRange   @ no, continue on
3267    b       common_errNullObject        @ yes, throw exception
3268
3269/* ------------------------------ */
3270    .balign 64
3271.L_OP_INVOKE_STATIC: /* 0x71 */
3272/* File: armv5te/OP_INVOKE_STATIC.S */
3273    /*
3274     * Handle a static method call.
3275     *
3276     * for: invoke-static, invoke-static/range
3277     */
3278    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3279    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3280    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3281    FETCH(r1, 1)                        @ r1<- BBBB
3282    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3283    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3284    cmp     r0, #0                      @ already resolved?
3285    EXPORT_PC()                         @ must export for invoke
3286    bne     common_invokeMethodNoRange @ yes, continue on
32870:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3288    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3289    mov     r2, #METHOD_STATIC          @ resolver method type
3290    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3291    cmp     r0, #0                      @ got null?
3292    bne     common_invokeMethodNoRange @ no, continue
3293    b       common_exceptionThrown      @ yes, handle exception
3294
3295
3296/* ------------------------------ */
3297    .balign 64
3298.L_OP_INVOKE_INTERFACE: /* 0x72 */
3299/* File: armv5te/OP_INVOKE_INTERFACE.S */
3300    /*
3301     * Handle an interface method call.
3302     *
3303     * for: invoke-interface, invoke-interface/range
3304     */
3305    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3306    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3307    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3308    FETCH(r1, 1)                        @ r1<- BBBB
3309    .if     (!0)
3310    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3311    .endif
3312    EXPORT_PC()                         @ must export for invoke
3313    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3314    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3315    cmp     r0, #0                      @ null obj?
3316    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3317    beq     common_errNullObject        @ yes, fail
3318    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3319    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3320    cmp     r0, #0                      @ failed?
3321    beq     common_exceptionThrown      @ yes, handle exception
3322    b       common_invokeMethodNoRange @ jump to common handler
3323
3324
3325/* ------------------------------ */
3326    .balign 64
3327.L_OP_UNUSED_73: /* 0x73 */
3328/* File: armv5te/OP_UNUSED_73.S */
3329/* File: armv5te/unused.S */
3330    bl      common_abort
3331
3332
3333
3334/* ------------------------------ */
3335    .balign 64
3336.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3337/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3338/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3339    /*
3340     * Handle a virtual method call.
3341     *
3342     * for: invoke-virtual, invoke-virtual/range
3343     */
3344    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3345    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3346    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3347    FETCH(r1, 1)                        @ r1<- BBBB
3348    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3349    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3350    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3351    .if     (!1)
3352    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3353    .endif
3354    cmp     r0, #0                      @ already resolved?
3355    EXPORT_PC()                         @ must export for invoke
3356    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3357    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3358    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3359    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3360    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3361    cmp     r0, #0                      @ got null?
3362    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3363    b       common_exceptionThrown      @ yes, handle exception
3364
3365
3366/* ------------------------------ */
3367    .balign 64
3368.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3369/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3370/* File: armv5te/OP_INVOKE_SUPER.S */
3371    /*
3372     * Handle a "super" method call.
3373     *
3374     * for: invoke-super, invoke-super/range
3375     */
3376    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3377    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3378    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3379    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3380    .if     (!1)
3381    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3382    .endif
3383    FETCH(r1, 1)                        @ r1<- BBBB
3384    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3385    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3386    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3387    cmp     r2, #0                      @ null "this"?
3388    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3389    beq     common_errNullObject        @ null "this", throw exception
3390    cmp     r0, #0                      @ already resolved?
3391    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3392    EXPORT_PC()                         @ must export for invoke
3393    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3394    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3395
3396
3397/* ------------------------------ */
3398    .balign 64
3399.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3400/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3401/* File: armv5te/OP_INVOKE_DIRECT.S */
3402    /*
3403     * Handle a direct method call.
3404     *
3405     * (We could defer the "is 'this' pointer null" test to the common
3406     * method invocation code, and use a flag to indicate that static
3407     * calls don't count.  If we do this as part of copying the arguments
3408     * out we could avoiding loading the first arg twice.)
3409     *
3410     * for: invoke-direct, invoke-direct/range
3411     */
3412    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3413    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3414    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3415    FETCH(r1, 1)                        @ r1<- BBBB
3416    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3417    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3418    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3419    .if     (!1)
3420    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3421    .endif
3422    cmp     r0, #0                      @ already resolved?
3423    EXPORT_PC()                         @ must export for invoke
3424    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3425    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3426.LOP_INVOKE_DIRECT_RANGE_finish:
3427    cmp     r2, #0                      @ null "this" ref?
3428    bne     common_invokeMethodRange   @ no, continue on
3429    b       common_errNullObject        @ yes, throw exception
3430
3431
3432/* ------------------------------ */
3433    .balign 64
3434.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3435/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3436/* File: armv5te/OP_INVOKE_STATIC.S */
3437    /*
3438     * Handle a static method call.
3439     *
3440     * for: invoke-static, invoke-static/range
3441     */
3442    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3443    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3444    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3445    FETCH(r1, 1)                        @ r1<- BBBB
3446    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3447    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3448    cmp     r0, #0                      @ already resolved?
3449    EXPORT_PC()                         @ must export for invoke
3450    bne     common_invokeMethodRange @ yes, continue on
34510:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3452    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3453    mov     r2, #METHOD_STATIC          @ resolver method type
3454    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3455    cmp     r0, #0                      @ got null?
3456    bne     common_invokeMethodRange @ no, continue
3457    b       common_exceptionThrown      @ yes, handle exception
3458
3459
3460
3461/* ------------------------------ */
3462    .balign 64
3463.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3464/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3465/* File: armv5te/OP_INVOKE_INTERFACE.S */
3466    /*
3467     * Handle an interface method call.
3468     *
3469     * for: invoke-interface, invoke-interface/range
3470     */
3471    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3472    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3473    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3474    FETCH(r1, 1)                        @ r1<- BBBB
3475    .if     (!1)
3476    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3477    .endif
3478    EXPORT_PC()                         @ must export for invoke
3479    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3480    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3481    cmp     r0, #0                      @ null obj?
3482    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3483    beq     common_errNullObject        @ yes, fail
3484    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3485    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3486    cmp     r0, #0                      @ failed?
3487    beq     common_exceptionThrown      @ yes, handle exception
3488    b       common_invokeMethodRange @ jump to common handler
3489
3490
3491
3492/* ------------------------------ */
3493    .balign 64
3494.L_OP_UNUSED_79: /* 0x79 */
3495/* File: armv5te/OP_UNUSED_79.S */
3496/* File: armv5te/unused.S */
3497    bl      common_abort
3498
3499
3500
3501/* ------------------------------ */
3502    .balign 64
3503.L_OP_UNUSED_7A: /* 0x7a */
3504/* File: armv5te/OP_UNUSED_7A.S */
3505/* File: armv5te/unused.S */
3506    bl      common_abort
3507
3508
3509
3510/* ------------------------------ */
3511    .balign 64
3512.L_OP_NEG_INT: /* 0x7b */
3513/* File: armv5te/OP_NEG_INT.S */
3514/* File: armv5te/unop.S */
3515    /*
3516     * Generic 32-bit unary operation.  Provide an "instr" line that
3517     * specifies an instruction that performs "result = op r0".
3518     * This could be an ARM instruction or a function call.
3519     *
3520     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3521     *      int-to-byte, int-to-char, int-to-short
3522     */
3523    /* unop vA, vB */
3524    mov     r3, rINST, lsr #12          @ r3<- B
3525    mov     r9, rINST, lsr #8           @ r9<- A+
3526    GET_VREG(r0, r3)                    @ r0<- vB
3527    and     r9, r9, #15
3528                               @ optional op; may set condition codes
3529    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3530    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3532    SET_VREG(r0, r9)                    @ vAA<- r0
3533    GOTO_OPCODE(ip)                     @ jump to next instruction
3534    /* 9-10 instructions */
3535
3536
3537/* ------------------------------ */
3538    .balign 64
3539.L_OP_NOT_INT: /* 0x7c */
3540/* File: armv5te/OP_NOT_INT.S */
3541/* File: armv5te/unop.S */
3542    /*
3543     * Generic 32-bit unary operation.  Provide an "instr" line that
3544     * specifies an instruction that performs "result = op r0".
3545     * This could be an ARM instruction or a function call.
3546     *
3547     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3548     *      int-to-byte, int-to-char, int-to-short
3549     */
3550    /* unop vA, vB */
3551    mov     r3, rINST, lsr #12          @ r3<- B
3552    mov     r9, rINST, lsr #8           @ r9<- A+
3553    GET_VREG(r0, r3)                    @ r0<- vB
3554    and     r9, r9, #15
3555                               @ optional op; may set condition codes
3556    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3557    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3559    SET_VREG(r0, r9)                    @ vAA<- r0
3560    GOTO_OPCODE(ip)                     @ jump to next instruction
3561    /* 9-10 instructions */
3562
3563
3564/* ------------------------------ */
3565    .balign 64
3566.L_OP_NEG_LONG: /* 0x7d */
3567/* File: armv5te/OP_NEG_LONG.S */
3568/* File: armv5te/unopWide.S */
3569    /*
3570     * Generic 64-bit unary operation.  Provide an "instr" line that
3571     * specifies an instruction that performs "result = op r0/r1".
3572     * This could be an ARM instruction or a function call.
3573     *
3574     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3575     */
3576    /* unop vA, vB */
3577    mov     r9, rINST, lsr #8           @ r9<- A+
3578    mov     r3, rINST, lsr #12          @ r3<- B
3579    and     r9, r9, #15
3580    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3581    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3582    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3583    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3584    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3585    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3587    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3588    GOTO_OPCODE(ip)                     @ jump to next instruction
3589    /* 12-13 instructions */
3590
3591
3592
3593/* ------------------------------ */
3594    .balign 64
3595.L_OP_NOT_LONG: /* 0x7e */
3596/* File: armv5te/OP_NOT_LONG.S */
3597/* File: armv5te/unopWide.S */
3598    /*
3599     * Generic 64-bit unary operation.  Provide an "instr" line that
3600     * specifies an instruction that performs "result = op r0/r1".
3601     * This could be an ARM instruction or a function call.
3602     *
3603     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3604     */
3605    /* unop vA, vB */
3606    mov     r9, rINST, lsr #8           @ r9<- A+
3607    mov     r3, rINST, lsr #12          @ r3<- B
3608    and     r9, r9, #15
3609    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3610    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3611    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3612    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3613    mvn     r0, r0                           @ optional op; may set condition codes
3614    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3615    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3616    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3617    GOTO_OPCODE(ip)                     @ jump to next instruction
3618    /* 12-13 instructions */
3619
3620
3621
3622/* ------------------------------ */
3623    .balign 64
3624.L_OP_NEG_FLOAT: /* 0x7f */
3625/* File: armv5te/OP_NEG_FLOAT.S */
3626/* File: armv5te/unop.S */
3627    /*
3628     * Generic 32-bit unary operation.  Provide an "instr" line that
3629     * specifies an instruction that performs "result = op r0".
3630     * This could be an ARM instruction or a function call.
3631     *
3632     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3633     *      int-to-byte, int-to-char, int-to-short
3634     */
3635    /* unop vA, vB */
3636    mov     r3, rINST, lsr #12          @ r3<- B
3637    mov     r9, rINST, lsr #8           @ r9<- A+
3638    GET_VREG(r0, r3)                    @ r0<- vB
3639    and     r9, r9, #15
3640                               @ optional op; may set condition codes
3641    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3642    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3643    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3644    SET_VREG(r0, r9)                    @ vAA<- r0
3645    GOTO_OPCODE(ip)                     @ jump to next instruction
3646    /* 9-10 instructions */
3647
3648
3649/* ------------------------------ */
3650    .balign 64
3651.L_OP_NEG_DOUBLE: /* 0x80 */
3652/* File: armv5te/OP_NEG_DOUBLE.S */
3653/* File: armv5te/unopWide.S */
3654    /*
3655     * Generic 64-bit unary operation.  Provide an "instr" line that
3656     * specifies an instruction that performs "result = op r0/r1".
3657     * This could be an ARM instruction or a function call.
3658     *
3659     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3660     */
3661    /* unop vA, vB */
3662    mov     r9, rINST, lsr #8           @ r9<- A+
3663    mov     r3, rINST, lsr #12          @ r3<- B
3664    and     r9, r9, #15
3665    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3666    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3667    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3668    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3669                               @ optional op; may set condition codes
3670    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3671    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3672    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3673    GOTO_OPCODE(ip)                     @ jump to next instruction
3674    /* 12-13 instructions */
3675
3676
3677
3678/* ------------------------------ */
3679    .balign 64
3680.L_OP_INT_TO_LONG: /* 0x81 */
3681/* File: armv5te/OP_INT_TO_LONG.S */
3682/* File: armv5te/unopWider.S */
3683    /*
3684     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3685     * that specifies an instruction that performs "result = op r0", where
3686     * "result" is a 64-bit quantity in r0/r1.
3687     *
3688     * For: int-to-long, int-to-double, float-to-long, float-to-double
3689     */
3690    /* unop vA, vB */
3691    mov     r9, rINST, lsr #8           @ r9<- A+
3692    mov     r3, rINST, lsr #12          @ r3<- B
3693    and     r9, r9, #15
3694    GET_VREG(r0, r3)                    @ r0<- vB
3695    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3696                               @ optional op; may set condition codes
3697    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3698    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3699    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3700    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3701    GOTO_OPCODE(ip)                     @ jump to next instruction
3702    /* 10-11 instructions */
3703
3704
3705/* ------------------------------ */
3706    .balign 64
3707.L_OP_INT_TO_FLOAT: /* 0x82 */
3708/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3709/* File: arm-vfp/funop.S */
3710    /*
3711     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3712     * line that specifies an instruction that performs "s1 = op s0".
3713     *
3714     * for: int-to-float, float-to-int
3715     */
3716    /* unop vA, vB */
3717    mov     r3, rINST, lsr #12          @ r3<- B
3718    mov     r9, rINST, lsr #8           @ r9<- A+
3719    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3720    flds    s0, [r3]                    @ s0<- vB
3721    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3722    and     r9, r9, #15                 @ r9<- A
3723    fsitos  s1, s0                              @ s1<- op
3724    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3725    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3726    fsts    s1, [r9]                    @ vA<- s1
3727    GOTO_OPCODE(ip)                     @ jump to next instruction
3728
3729
3730/* ------------------------------ */
3731    .balign 64
3732.L_OP_INT_TO_DOUBLE: /* 0x83 */
3733/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3734/* File: arm-vfp/funopWider.S */
3735    /*
3736     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3737     * "instr" line that specifies an instruction that performs "d0 = op s0".
3738     *
3739     * For: int-to-double, float-to-double
3740     */
3741    /* unop vA, vB */
3742    mov     r3, rINST, lsr #12          @ r3<- B
3743    mov     r9, rINST, lsr #8           @ r9<- A+
3744    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3745    flds    s0, [r3]                    @ s0<- vB
3746    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3747    and     r9, r9, #15                 @ r9<- A
3748    fsitod  d0, s0                              @ d0<- op
3749    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3750    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3751    fstd    d0, [r9]                    @ vA<- d0
3752    GOTO_OPCODE(ip)                     @ jump to next instruction
3753
3754
3755/* ------------------------------ */
3756    .balign 64
3757.L_OP_LONG_TO_INT: /* 0x84 */
3758/* File: armv5te/OP_LONG_TO_INT.S */
3759/* we ignore the high word, making this equivalent to a 32-bit reg move */
3760/* File: armv5te/OP_MOVE.S */
3761    /* for move, move-object, long-to-int */
3762    /* op vA, vB */
3763    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3764    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3765    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3766    GET_VREG(r2, r1)                    @ r2<- fp[B]
3767    and     r0, r0, #15
3768    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3769    SET_VREG(r2, r0)                    @ fp[A]<- r2
3770    GOTO_OPCODE(ip)                     @ execute next instruction
3771
3772
3773
3774/* ------------------------------ */
3775    .balign 64
3776.L_OP_LONG_TO_FLOAT: /* 0x85 */
3777/* File: armv5te/OP_LONG_TO_FLOAT.S */
3778/* File: armv5te/unopNarrower.S */
3779    /*
3780     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3781     * that specifies an instruction that performs "result = op r0/r1", where
3782     * "result" is a 32-bit quantity in r0.
3783     *
3784     * For: long-to-float, double-to-int, double-to-float
3785     *
3786     * (This would work for long-to-int, but that instruction is actually
3787     * an exact match for OP_MOVE.)
3788     */
3789    /* unop vA, vB */
3790    mov     r3, rINST, lsr #12          @ r3<- B
3791    mov     r9, rINST, lsr #8           @ r9<- A+
3792    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3793    and     r9, r9, #15
3794    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3795    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3796                               @ optional op; may set condition codes
3797    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3799    SET_VREG(r0, r9)                    @ vA<- r0
3800    GOTO_OPCODE(ip)                     @ jump to next instruction
3801    /* 10-11 instructions */
3802
3803
3804/* ------------------------------ */
3805    .balign 64
3806.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3807/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3808/* File: armv5te/unopWide.S */
3809    /*
3810     * Generic 64-bit unary operation.  Provide an "instr" line that
3811     * specifies an instruction that performs "result = op r0/r1".
3812     * This could be an ARM instruction or a function call.
3813     *
3814     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3815     */
3816    /* unop vA, vB */
3817    mov     r9, rINST, lsr #8           @ r9<- A+
3818    mov     r3, rINST, lsr #12          @ r3<- B
3819    and     r9, r9, #15
3820    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3821    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3822    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3823    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3824                               @ optional op; may set condition codes
3825    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3827    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3828    GOTO_OPCODE(ip)                     @ jump to next instruction
3829    /* 12-13 instructions */
3830
3831
3832
3833/* ------------------------------ */
3834    .balign 64
3835.L_OP_FLOAT_TO_INT: /* 0x87 */
3836/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3837/* File: arm-vfp/funop.S */
3838    /*
3839     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3840     * line that specifies an instruction that performs "s1 = op s0".
3841     *
3842     * for: int-to-float, float-to-int
3843     */
3844    /* unop vA, vB */
3845    mov     r3, rINST, lsr #12          @ r3<- B
3846    mov     r9, rINST, lsr #8           @ r9<- A+
3847    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3848    flds    s0, [r3]                    @ s0<- vB
3849    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3850    and     r9, r9, #15                 @ r9<- A
3851    ftosizs s1, s0                              @ s1<- op
3852    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3853    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3854    fsts    s1, [r9]                    @ vA<- s1
3855    GOTO_OPCODE(ip)                     @ jump to next instruction
3856
3857
3858/* ------------------------------ */
3859    .balign 64
3860.L_OP_FLOAT_TO_LONG: /* 0x88 */
3861/* File: armv5te/OP_FLOAT_TO_LONG.S */
3862@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3863/* File: armv5te/unopWider.S */
3864    /*
3865     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3866     * that specifies an instruction that performs "result = op r0", where
3867     * "result" is a 64-bit quantity in r0/r1.
3868     *
3869     * For: int-to-long, int-to-double, float-to-long, float-to-double
3870     */
3871    /* unop vA, vB */
3872    mov     r9, rINST, lsr #8           @ r9<- A+
3873    mov     r3, rINST, lsr #12          @ r3<- B
3874    and     r9, r9, #15
3875    GET_VREG(r0, r3)                    @ r0<- vB
3876    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3877                               @ optional op; may set condition codes
3878    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3879    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3880    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3881    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3882    GOTO_OPCODE(ip)                     @ jump to next instruction
3883    /* 10-11 instructions */
3884
3885
3886
3887/* ------------------------------ */
3888    .balign 64
3889.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3890/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3891/* File: arm-vfp/funopWider.S */
3892    /*
3893     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3894     * "instr" line that specifies an instruction that performs "d0 = op s0".
3895     *
3896     * For: int-to-double, float-to-double
3897     */
3898    /* unop vA, vB */
3899    mov     r3, rINST, lsr #12          @ r3<- B
3900    mov     r9, rINST, lsr #8           @ r9<- A+
3901    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3902    flds    s0, [r3]                    @ s0<- vB
3903    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3904    and     r9, r9, #15                 @ r9<- A
3905    fcvtds  d0, s0                              @ d0<- op
3906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3907    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3908    fstd    d0, [r9]                    @ vA<- d0
3909    GOTO_OPCODE(ip)                     @ jump to next instruction
3910
3911
3912/* ------------------------------ */
3913    .balign 64
3914.L_OP_DOUBLE_TO_INT: /* 0x8a */
3915/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3916/* File: arm-vfp/funopNarrower.S */
3917    /*
3918     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3919     * "instr" line that specifies an instruction that performs "s0 = op d0".
3920     *
3921     * For: double-to-int, double-to-float
3922     */
3923    /* unop vA, vB */
3924    mov     r3, rINST, lsr #12          @ r3<- B
3925    mov     r9, rINST, lsr #8           @ r9<- A+
3926    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3927    fldd    d0, [r3]                    @ d0<- vB
3928    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3929    and     r9, r9, #15                 @ r9<- A
3930    ftosizd  s0, d0                              @ s0<- op
3931    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3932    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3933    fsts    s0, [r9]                    @ vA<- s0
3934    GOTO_OPCODE(ip)                     @ jump to next instruction
3935
3936
3937/* ------------------------------ */
3938    .balign 64
3939.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3940/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3941@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3942/* File: armv5te/unopWide.S */
3943    /*
3944     * Generic 64-bit unary operation.  Provide an "instr" line that
3945     * specifies an instruction that performs "result = op r0/r1".
3946     * This could be an ARM instruction or a function call.
3947     *
3948     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3949     */
3950    /* unop vA, vB */
3951    mov     r9, rINST, lsr #8           @ r9<- A+
3952    mov     r3, rINST, lsr #12          @ r3<- B
3953    and     r9, r9, #15
3954    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3955    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3956    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3957    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3958                               @ optional op; may set condition codes
3959    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3961    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3962    GOTO_OPCODE(ip)                     @ jump to next instruction
3963    /* 12-13 instructions */
3964
3965
3966
3967
3968/* ------------------------------ */
3969    .balign 64
3970.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3971/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3972/* File: arm-vfp/funopNarrower.S */
3973    /*
3974     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3975     * "instr" line that specifies an instruction that performs "s0 = op d0".
3976     *
3977     * For: double-to-int, double-to-float
3978     */
3979    /* unop vA, vB */
3980    mov     r3, rINST, lsr #12          @ r3<- B
3981    mov     r9, rINST, lsr #8           @ r9<- A+
3982    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3983    fldd    d0, [r3]                    @ d0<- vB
3984    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3985    and     r9, r9, #15                 @ r9<- A
3986    fcvtsd  s0, d0                              @ s0<- op
3987    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3988    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3989    fsts    s0, [r9]                    @ vA<- s0
3990    GOTO_OPCODE(ip)                     @ jump to next instruction
3991
3992
3993/* ------------------------------ */
3994    .balign 64
3995.L_OP_INT_TO_BYTE: /* 0x8d */
3996/* File: armv5te/OP_INT_TO_BYTE.S */
3997/* File: armv5te/unop.S */
3998    /*
3999     * Generic 32-bit unary operation.  Provide an "instr" line that
4000     * specifies an instruction that performs "result = op r0".
4001     * This could be an ARM instruction or a function call.
4002     *
4003     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4004     *      int-to-byte, int-to-char, int-to-short
4005     */
4006    /* unop vA, vB */
4007    mov     r3, rINST, lsr #12          @ r3<- B
4008    mov     r9, rINST, lsr #8           @ r9<- A+
4009    GET_VREG(r0, r3)                    @ r0<- vB
4010    and     r9, r9, #15
4011    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4012    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4013    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4014    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4015    SET_VREG(r0, r9)                    @ vAA<- r0
4016    GOTO_OPCODE(ip)                     @ jump to next instruction
4017    /* 9-10 instructions */
4018
4019
4020/* ------------------------------ */
4021    .balign 64
4022.L_OP_INT_TO_CHAR: /* 0x8e */
4023/* File: armv5te/OP_INT_TO_CHAR.S */
4024/* File: armv5te/unop.S */
4025    /*
4026     * Generic 32-bit unary operation.  Provide an "instr" line that
4027     * specifies an instruction that performs "result = op r0".
4028     * This could be an ARM instruction or a function call.
4029     *
4030     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4031     *      int-to-byte, int-to-char, int-to-short
4032     */
4033    /* unop vA, vB */
4034    mov     r3, rINST, lsr #12          @ r3<- B
4035    mov     r9, rINST, lsr #8           @ r9<- A+
4036    GET_VREG(r0, r3)                    @ r0<- vB
4037    and     r9, r9, #15
4038    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4039    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4040    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4042    SET_VREG(r0, r9)                    @ vAA<- r0
4043    GOTO_OPCODE(ip)                     @ jump to next instruction
4044    /* 9-10 instructions */
4045
4046
4047/* ------------------------------ */
4048    .balign 64
4049.L_OP_INT_TO_SHORT: /* 0x8f */
4050/* File: armv5te/OP_INT_TO_SHORT.S */
4051/* File: armv5te/unop.S */
4052    /*
4053     * Generic 32-bit unary operation.  Provide an "instr" line that
4054     * specifies an instruction that performs "result = op r0".
4055     * This could be an ARM instruction or a function call.
4056     *
4057     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4058     *      int-to-byte, int-to-char, int-to-short
4059     */
4060    /* unop vA, vB */
4061    mov     r3, rINST, lsr #12          @ r3<- B
4062    mov     r9, rINST, lsr #8           @ r9<- A+
4063    GET_VREG(r0, r3)                    @ r0<- vB
4064    and     r9, r9, #15
4065    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4066    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4067    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4068    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4069    SET_VREG(r0, r9)                    @ vAA<- r0
4070    GOTO_OPCODE(ip)                     @ jump to next instruction
4071    /* 9-10 instructions */
4072
4073
4074/* ------------------------------ */
4075    .balign 64
4076.L_OP_ADD_INT: /* 0x90 */
4077/* File: armv5te/OP_ADD_INT.S */
4078/* File: armv5te/binop.S */
4079    /*
4080     * Generic 32-bit binary operation.  Provide an "instr" line that
4081     * specifies an instruction that performs "result = r0 op r1".
4082     * This could be an ARM instruction or a function call.  (If the result
4083     * comes back in a register other than r0, you can override "result".)
4084     *
4085     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4086     * vCC (r1).  Useful for integer division and modulus.  Note that we
4087     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4088     * handles it correctly.
4089     *
4090     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4091     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4092     *      mul-float, div-float, rem-float
4093     */
4094    /* binop vAA, vBB, vCC */
4095    FETCH(r0, 1)                        @ r0<- CCBB
4096    mov     r9, rINST, lsr #8           @ r9<- AA
4097    mov     r3, r0, lsr #8              @ r3<- CC
4098    and     r2, r0, #255                @ r2<- BB
4099    GET_VREG(r1, r3)                    @ r1<- vCC
4100    GET_VREG(r0, r2)                    @ r0<- vBB
4101    .if 0
4102    cmp     r1, #0                      @ is second operand zero?
4103    beq     common_errDivideByZero
4104    .endif
4105
4106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4107                               @ optional op; may set condition codes
4108    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4109    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4110    SET_VREG(r0, r9)               @ vAA<- r0
4111    GOTO_OPCODE(ip)                     @ jump to next instruction
4112    /* 11-14 instructions */
4113
4114
4115
4116/* ------------------------------ */
4117    .balign 64
4118.L_OP_SUB_INT: /* 0x91 */
4119/* File: armv5te/OP_SUB_INT.S */
4120/* File: armv5te/binop.S */
4121    /*
4122     * Generic 32-bit binary operation.  Provide an "instr" line that
4123     * specifies an instruction that performs "result = r0 op r1".
4124     * This could be an ARM instruction or a function call.  (If the result
4125     * comes back in a register other than r0, you can override "result".)
4126     *
4127     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4128     * vCC (r1).  Useful for integer division and modulus.  Note that we
4129     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4130     * handles it correctly.
4131     *
4132     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4133     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4134     *      mul-float, div-float, rem-float
4135     */
4136    /* binop vAA, vBB, vCC */
4137    FETCH(r0, 1)                        @ r0<- CCBB
4138    mov     r9, rINST, lsr #8           @ r9<- AA
4139    mov     r3, r0, lsr #8              @ r3<- CC
4140    and     r2, r0, #255                @ r2<- BB
4141    GET_VREG(r1, r3)                    @ r1<- vCC
4142    GET_VREG(r0, r2)                    @ r0<- vBB
4143    .if 0
4144    cmp     r1, #0                      @ is second operand zero?
4145    beq     common_errDivideByZero
4146    .endif
4147
4148    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4149                               @ optional op; may set condition codes
4150    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4152    SET_VREG(r0, r9)               @ vAA<- r0
4153    GOTO_OPCODE(ip)                     @ jump to next instruction
4154    /* 11-14 instructions */
4155
4156
4157
4158/* ------------------------------ */
4159    .balign 64
4160.L_OP_MUL_INT: /* 0x92 */
4161/* File: armv5te/OP_MUL_INT.S */
4162/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4163/* File: armv5te/binop.S */
4164    /*
4165     * Generic 32-bit binary operation.  Provide an "instr" line that
4166     * specifies an instruction that performs "result = r0 op r1".
4167     * This could be an ARM instruction or a function call.  (If the result
4168     * comes back in a register other than r0, you can override "result".)
4169     *
4170     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4171     * vCC (r1).  Useful for integer division and modulus.  Note that we
4172     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4173     * handles it correctly.
4174     *
4175     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4176     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4177     *      mul-float, div-float, rem-float
4178     */
4179    /* binop vAA, vBB, vCC */
4180    FETCH(r0, 1)                        @ r0<- CCBB
4181    mov     r9, rINST, lsr #8           @ r9<- AA
4182    mov     r3, r0, lsr #8              @ r3<- CC
4183    and     r2, r0, #255                @ r2<- BB
4184    GET_VREG(r1, r3)                    @ r1<- vCC
4185    GET_VREG(r0, r2)                    @ r0<- vBB
4186    .if 0
4187    cmp     r1, #0                      @ is second operand zero?
4188    beq     common_errDivideByZero
4189    .endif
4190
4191    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4192                               @ optional op; may set condition codes
4193    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4194    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4195    SET_VREG(r0, r9)               @ vAA<- r0
4196    GOTO_OPCODE(ip)                     @ jump to next instruction
4197    /* 11-14 instructions */
4198
4199
4200
4201/* ------------------------------ */
4202    .balign 64
4203.L_OP_DIV_INT: /* 0x93 */
4204/* File: armv5te/OP_DIV_INT.S */
4205/* File: armv5te/binop.S */
4206    /*
4207     * Generic 32-bit binary operation.  Provide an "instr" line that
4208     * specifies an instruction that performs "result = r0 op r1".
4209     * This could be an ARM instruction or a function call.  (If the result
4210     * comes back in a register other than r0, you can override "result".)
4211     *
4212     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4213     * vCC (r1).  Useful for integer division and modulus.  Note that we
4214     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4215     * handles it correctly.
4216     *
4217     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4218     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4219     *      mul-float, div-float, rem-float
4220     */
4221    /* binop vAA, vBB, vCC */
4222    FETCH(r0, 1)                        @ r0<- CCBB
4223    mov     r9, rINST, lsr #8           @ r9<- AA
4224    mov     r3, r0, lsr #8              @ r3<- CC
4225    and     r2, r0, #255                @ r2<- BB
4226    GET_VREG(r1, r3)                    @ r1<- vCC
4227    GET_VREG(r0, r2)                    @ r0<- vBB
4228    .if 1
4229    cmp     r1, #0                      @ is second operand zero?
4230    beq     common_errDivideByZero
4231    .endif
4232
4233    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4234                               @ optional op; may set condition codes
4235    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4237    SET_VREG(r0, r9)               @ vAA<- r0
4238    GOTO_OPCODE(ip)                     @ jump to next instruction
4239    /* 11-14 instructions */
4240
4241
4242
4243/* ------------------------------ */
4244    .balign 64
4245.L_OP_REM_INT: /* 0x94 */
4246/* File: armv5te/OP_REM_INT.S */
4247/* idivmod returns quotient in r0 and remainder in r1 */
4248/* File: armv5te/binop.S */
4249    /*
4250     * Generic 32-bit binary operation.  Provide an "instr" line that
4251     * specifies an instruction that performs "result = r0 op r1".
4252     * This could be an ARM instruction or a function call.  (If the result
4253     * comes back in a register other than r0, you can override "result".)
4254     *
4255     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4256     * vCC (r1).  Useful for integer division and modulus.  Note that we
4257     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4258     * handles it correctly.
4259     *
4260     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4261     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4262     *      mul-float, div-float, rem-float
4263     */
4264    /* binop vAA, vBB, vCC */
4265    FETCH(r0, 1)                        @ r0<- CCBB
4266    mov     r9, rINST, lsr #8           @ r9<- AA
4267    mov     r3, r0, lsr #8              @ r3<- CC
4268    and     r2, r0, #255                @ r2<- BB
4269    GET_VREG(r1, r3)                    @ r1<- vCC
4270    GET_VREG(r0, r2)                    @ r0<- vBB
4271    .if 1
4272    cmp     r1, #0                      @ is second operand zero?
4273    beq     common_errDivideByZero
4274    .endif
4275
4276    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4277                               @ optional op; may set condition codes
4278    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4279    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4280    SET_VREG(r1, r9)               @ vAA<- r1
4281    GOTO_OPCODE(ip)                     @ jump to next instruction
4282    /* 11-14 instructions */
4283
4284
4285
4286/* ------------------------------ */
4287    .balign 64
4288.L_OP_AND_INT: /* 0x95 */
4289/* File: armv5te/OP_AND_INT.S */
4290/* File: armv5te/binop.S */
4291    /*
4292     * Generic 32-bit binary operation.  Provide an "instr" line that
4293     * specifies an instruction that performs "result = r0 op r1".
4294     * This could be an ARM instruction or a function call.  (If the result
4295     * comes back in a register other than r0, you can override "result".)
4296     *
4297     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4298     * vCC (r1).  Useful for integer division and modulus.  Note that we
4299     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4300     * handles it correctly.
4301     *
4302     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4303     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4304     *      mul-float, div-float, rem-float
4305     */
4306    /* binop vAA, vBB, vCC */
4307    FETCH(r0, 1)                        @ r0<- CCBB
4308    mov     r9, rINST, lsr #8           @ r9<- AA
4309    mov     r3, r0, lsr #8              @ r3<- CC
4310    and     r2, r0, #255                @ r2<- BB
4311    GET_VREG(r1, r3)                    @ r1<- vCC
4312    GET_VREG(r0, r2)                    @ r0<- vBB
4313    .if 0
4314    cmp     r1, #0                      @ is second operand zero?
4315    beq     common_errDivideByZero
4316    .endif
4317
4318    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4319                               @ optional op; may set condition codes
4320    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4321    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4322    SET_VREG(r0, r9)               @ vAA<- r0
4323    GOTO_OPCODE(ip)                     @ jump to next instruction
4324    /* 11-14 instructions */
4325
4326
4327
4328/* ------------------------------ */
4329    .balign 64
4330.L_OP_OR_INT: /* 0x96 */
4331/* File: armv5te/OP_OR_INT.S */
4332/* File: armv5te/binop.S */
4333    /*
4334     * Generic 32-bit binary operation.  Provide an "instr" line that
4335     * specifies an instruction that performs "result = r0 op r1".
4336     * This could be an ARM instruction or a function call.  (If the result
4337     * comes back in a register other than r0, you can override "result".)
4338     *
4339     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4340     * vCC (r1).  Useful for integer division and modulus.  Note that we
4341     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4342     * handles it correctly.
4343     *
4344     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4345     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4346     *      mul-float, div-float, rem-float
4347     */
4348    /* binop vAA, vBB, vCC */
4349    FETCH(r0, 1)                        @ r0<- CCBB
4350    mov     r9, rINST, lsr #8           @ r9<- AA
4351    mov     r3, r0, lsr #8              @ r3<- CC
4352    and     r2, r0, #255                @ r2<- BB
4353    GET_VREG(r1, r3)                    @ r1<- vCC
4354    GET_VREG(r0, r2)                    @ r0<- vBB
4355    .if 0
4356    cmp     r1, #0                      @ is second operand zero?
4357    beq     common_errDivideByZero
4358    .endif
4359
4360    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4361                               @ optional op; may set condition codes
4362    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4363    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4364    SET_VREG(r0, r9)               @ vAA<- r0
4365    GOTO_OPCODE(ip)                     @ jump to next instruction
4366    /* 11-14 instructions */
4367
4368
4369
4370/* ------------------------------ */
4371    .balign 64
4372.L_OP_XOR_INT: /* 0x97 */
4373/* File: armv5te/OP_XOR_INT.S */
4374/* File: armv5te/binop.S */
4375    /*
4376     * Generic 32-bit binary operation.  Provide an "instr" line that
4377     * specifies an instruction that performs "result = r0 op r1".
4378     * This could be an ARM instruction or a function call.  (If the result
4379     * comes back in a register other than r0, you can override "result".)
4380     *
4381     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4382     * vCC (r1).  Useful for integer division and modulus.  Note that we
4383     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4384     * handles it correctly.
4385     *
4386     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4387     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4388     *      mul-float, div-float, rem-float
4389     */
4390    /* binop vAA, vBB, vCC */
4391    FETCH(r0, 1)                        @ r0<- CCBB
4392    mov     r9, rINST, lsr #8           @ r9<- AA
4393    mov     r3, r0, lsr #8              @ r3<- CC
4394    and     r2, r0, #255                @ r2<- BB
4395    GET_VREG(r1, r3)                    @ r1<- vCC
4396    GET_VREG(r0, r2)                    @ r0<- vBB
4397    .if 0
4398    cmp     r1, #0                      @ is second operand zero?
4399    beq     common_errDivideByZero
4400    .endif
4401
4402    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4403                               @ optional op; may set condition codes
4404    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4406    SET_VREG(r0, r9)               @ vAA<- r0
4407    GOTO_OPCODE(ip)                     @ jump to next instruction
4408    /* 11-14 instructions */
4409
4410
4411
4412/* ------------------------------ */
4413    .balign 64
4414.L_OP_SHL_INT: /* 0x98 */
4415/* File: armv5te/OP_SHL_INT.S */
4416/* File: armv5te/binop.S */
4417    /*
4418     * Generic 32-bit binary operation.  Provide an "instr" line that
4419     * specifies an instruction that performs "result = r0 op r1".
4420     * This could be an ARM instruction or a function call.  (If the result
4421     * comes back in a register other than r0, you can override "result".)
4422     *
4423     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4424     * vCC (r1).  Useful for integer division and modulus.  Note that we
4425     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4426     * handles it correctly.
4427     *
4428     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4429     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4430     *      mul-float, div-float, rem-float
4431     */
4432    /* binop vAA, vBB, vCC */
4433    FETCH(r0, 1)                        @ r0<- CCBB
4434    mov     r9, rINST, lsr #8           @ r9<- AA
4435    mov     r3, r0, lsr #8              @ r3<- CC
4436    and     r2, r0, #255                @ r2<- BB
4437    GET_VREG(r1, r3)                    @ r1<- vCC
4438    GET_VREG(r0, r2)                    @ r0<- vBB
4439    .if 0
4440    cmp     r1, #0                      @ is second operand zero?
4441    beq     common_errDivideByZero
4442    .endif
4443
4444    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4445    and     r1, r1, #31                           @ optional op; may set condition codes
4446    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4448    SET_VREG(r0, r9)               @ vAA<- r0
4449    GOTO_OPCODE(ip)                     @ jump to next instruction
4450    /* 11-14 instructions */
4451
4452
4453
4454/* ------------------------------ */
4455    .balign 64
4456.L_OP_SHR_INT: /* 0x99 */
4457/* File: armv5te/OP_SHR_INT.S */
4458/* File: armv5te/binop.S */
4459    /*
4460     * Generic 32-bit binary operation.  Provide an "instr" line that
4461     * specifies an instruction that performs "result = r0 op r1".
4462     * This could be an ARM instruction or a function call.  (If the result
4463     * comes back in a register other than r0, you can override "result".)
4464     *
4465     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4466     * vCC (r1).  Useful for integer division and modulus.  Note that we
4467     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4468     * handles it correctly.
4469     *
4470     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4471     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4472     *      mul-float, div-float, rem-float
4473     */
4474    /* binop vAA, vBB, vCC */
4475    FETCH(r0, 1)                        @ r0<- CCBB
4476    mov     r9, rINST, lsr #8           @ r9<- AA
4477    mov     r3, r0, lsr #8              @ r3<- CC
4478    and     r2, r0, #255                @ r2<- BB
4479    GET_VREG(r1, r3)                    @ r1<- vCC
4480    GET_VREG(r0, r2)                    @ r0<- vBB
4481    .if 0
4482    cmp     r1, #0                      @ is second operand zero?
4483    beq     common_errDivideByZero
4484    .endif
4485
4486    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4487    and     r1, r1, #31                           @ optional op; may set condition codes
4488    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4489    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4490    SET_VREG(r0, r9)               @ vAA<- r0
4491    GOTO_OPCODE(ip)                     @ jump to next instruction
4492    /* 11-14 instructions */
4493
4494
4495
4496/* ------------------------------ */
4497    .balign 64
4498.L_OP_USHR_INT: /* 0x9a */
4499/* File: armv5te/OP_USHR_INT.S */
4500/* File: armv5te/binop.S */
4501    /*
4502     * Generic 32-bit binary operation.  Provide an "instr" line that
4503     * specifies an instruction that performs "result = r0 op r1".
4504     * This could be an ARM instruction or a function call.  (If the result
4505     * comes back in a register other than r0, you can override "result".)
4506     *
4507     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4508     * vCC (r1).  Useful for integer division and modulus.  Note that we
4509     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4510     * handles it correctly.
4511     *
4512     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4513     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4514     *      mul-float, div-float, rem-float
4515     */
4516    /* binop vAA, vBB, vCC */
4517    FETCH(r0, 1)                        @ r0<- CCBB
4518    mov     r9, rINST, lsr #8           @ r9<- AA
4519    mov     r3, r0, lsr #8              @ r3<- CC
4520    and     r2, r0, #255                @ r2<- BB
4521    GET_VREG(r1, r3)                    @ r1<- vCC
4522    GET_VREG(r0, r2)                    @ r0<- vBB
4523    .if 0
4524    cmp     r1, #0                      @ is second operand zero?
4525    beq     common_errDivideByZero
4526    .endif
4527
4528    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4529    and     r1, r1, #31                           @ optional op; may set condition codes
4530    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4532    SET_VREG(r0, r9)               @ vAA<- r0
4533    GOTO_OPCODE(ip)                     @ jump to next instruction
4534    /* 11-14 instructions */
4535
4536
4537
4538/* ------------------------------ */
4539    .balign 64
4540.L_OP_ADD_LONG: /* 0x9b */
4541/* File: armv5te/OP_ADD_LONG.S */
4542/* File: armv5te/binopWide.S */
4543    /*
4544     * Generic 64-bit binary operation.  Provide an "instr" line that
4545     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4546     * This could be an ARM instruction or a function call.  (If the result
4547     * comes back in a register other than r0, you can override "result".)
4548     *
4549     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4550     * vCC (r1).  Useful for integer division and modulus.
4551     *
4552     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4553     *      xor-long, add-double, sub-double, mul-double, div-double,
4554     *      rem-double
4555     *
4556     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4557     */
4558    /* binop vAA, vBB, vCC */
4559    FETCH(r0, 1)                        @ r0<- CCBB
4560    mov     r9, rINST, lsr #8           @ r9<- AA
4561    and     r2, r0, #255                @ r2<- BB
4562    mov     r3, r0, lsr #8              @ r3<- CC
4563    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4564    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4565    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4566    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4567    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4568    .if 0
4569    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4570    beq     common_errDivideByZero
4571    .endif
4572    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4573
4574    adds    r0, r0, r2                           @ optional op; may set condition codes
4575    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4577    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4578    GOTO_OPCODE(ip)                     @ jump to next instruction
4579    /* 14-17 instructions */
4580
4581
4582
4583/* ------------------------------ */
4584    .balign 64
4585.L_OP_SUB_LONG: /* 0x9c */
4586/* File: armv5te/OP_SUB_LONG.S */
4587/* File: armv5te/binopWide.S */
4588    /*
4589     * Generic 64-bit binary operation.  Provide an "instr" line that
4590     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4591     * This could be an ARM instruction or a function call.  (If the result
4592     * comes back in a register other than r0, you can override "result".)
4593     *
4594     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4595     * vCC (r1).  Useful for integer division and modulus.
4596     *
4597     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4598     *      xor-long, add-double, sub-double, mul-double, div-double,
4599     *      rem-double
4600     *
4601     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4602     */
4603    /* binop vAA, vBB, vCC */
4604    FETCH(r0, 1)                        @ r0<- CCBB
4605    mov     r9, rINST, lsr #8           @ r9<- AA
4606    and     r2, r0, #255                @ r2<- BB
4607    mov     r3, r0, lsr #8              @ r3<- CC
4608    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4609    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4610    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4611    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4612    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4613    .if 0
4614    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4615    beq     common_errDivideByZero
4616    .endif
4617    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4618
4619    subs    r0, r0, r2                           @ optional op; may set condition codes
4620    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4621    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4622    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4623    GOTO_OPCODE(ip)                     @ jump to next instruction
4624    /* 14-17 instructions */
4625
4626
4627
4628/* ------------------------------ */
4629    .balign 64
4630.L_OP_MUL_LONG: /* 0x9d */
4631/* File: armv5te/OP_MUL_LONG.S */
4632    /*
4633     * Signed 64-bit integer multiply.
4634     *
4635     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4636     *        WX
4637     *      x YZ
4638     *  --------
4639     *     ZW ZX
4640     *  YW YX
4641     *
4642     * The low word of the result holds ZX, the high word holds
4643     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4644     * it doesn't fit in the low 64 bits.
4645     *
4646     * Unlike most ARM math operations, multiply instructions have
4647     * restrictions on using the same register more than once (Rd and Rm
4648     * cannot be the same).
4649     */
4650    /* mul-long vAA, vBB, vCC */
4651    FETCH(r0, 1)                        @ r0<- CCBB
4652    and     r2, r0, #255                @ r2<- BB
4653    mov     r3, r0, lsr #8              @ r3<- CC
4654    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4655    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4656    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4657    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4658    mul     ip, r2, r1                  @  ip<- ZxW
4659    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4660    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4661    mov     r0, rINST, lsr #8           @ r0<- AA
4662    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4663    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4664    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4665    b       .LOP_MUL_LONG_finish
4666
4667/* ------------------------------ */
4668    .balign 64
4669.L_OP_DIV_LONG: /* 0x9e */
4670/* File: armv5te/OP_DIV_LONG.S */
4671/* File: armv5te/binopWide.S */
4672    /*
4673     * Generic 64-bit binary operation.  Provide an "instr" line that
4674     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4675     * This could be an ARM instruction or a function call.  (If the result
4676     * comes back in a register other than r0, you can override "result".)
4677     *
4678     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4679     * vCC (r1).  Useful for integer division and modulus.
4680     *
4681     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4682     *      xor-long, add-double, sub-double, mul-double, div-double,
4683     *      rem-double
4684     *
4685     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4686     */
4687    /* binop vAA, vBB, vCC */
4688    FETCH(r0, 1)                        @ r0<- CCBB
4689    mov     r9, rINST, lsr #8           @ r9<- AA
4690    and     r2, r0, #255                @ r2<- BB
4691    mov     r3, r0, lsr #8              @ r3<- CC
4692    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4693    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4694    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4695    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4696    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4697    .if 1
4698    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4699    beq     common_errDivideByZero
4700    .endif
4701    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4702
4703                               @ optional op; may set condition codes
4704    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4706    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4707    GOTO_OPCODE(ip)                     @ jump to next instruction
4708    /* 14-17 instructions */
4709
4710
4711
4712/* ------------------------------ */
4713    .balign 64
4714.L_OP_REM_LONG: /* 0x9f */
4715/* File: armv5te/OP_REM_LONG.S */
4716/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4717/* File: armv5te/binopWide.S */
4718    /*
4719     * Generic 64-bit binary operation.  Provide an "instr" line that
4720     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4721     * This could be an ARM instruction or a function call.  (If the result
4722     * comes back in a register other than r0, you can override "result".)
4723     *
4724     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4725     * vCC (r1).  Useful for integer division and modulus.
4726     *
4727     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4728     *      xor-long, add-double, sub-double, mul-double, div-double,
4729     *      rem-double
4730     *
4731     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4732     */
4733    /* binop vAA, vBB, vCC */
4734    FETCH(r0, 1)                        @ r0<- CCBB
4735    mov     r9, rINST, lsr #8           @ r9<- AA
4736    and     r2, r0, #255                @ r2<- BB
4737    mov     r3, r0, lsr #8              @ r3<- CC
4738    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4739    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4740    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4741    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4742    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4743    .if 1
4744    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4745    beq     common_errDivideByZero
4746    .endif
4747    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4748
4749                               @ optional op; may set condition codes
4750    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4752    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4753    GOTO_OPCODE(ip)                     @ jump to next instruction
4754    /* 14-17 instructions */
4755
4756
4757
4758/* ------------------------------ */
4759    .balign 64
4760.L_OP_AND_LONG: /* 0xa0 */
4761/* File: armv5te/OP_AND_LONG.S */
4762/* File: armv5te/binopWide.S */
4763    /*
4764     * Generic 64-bit binary operation.  Provide an "instr" line that
4765     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4766     * This could be an ARM instruction or a function call.  (If the result
4767     * comes back in a register other than r0, you can override "result".)
4768     *
4769     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4770     * vCC (r1).  Useful for integer division and modulus.
4771     *
4772     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4773     *      xor-long, add-double, sub-double, mul-double, div-double,
4774     *      rem-double
4775     *
4776     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4777     */
4778    /* binop vAA, vBB, vCC */
4779    FETCH(r0, 1)                        @ r0<- CCBB
4780    mov     r9, rINST, lsr #8           @ r9<- AA
4781    and     r2, r0, #255                @ r2<- BB
4782    mov     r3, r0, lsr #8              @ r3<- CC
4783    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4784    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4785    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4786    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4787    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4788    .if 0
4789    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4790    beq     common_errDivideByZero
4791    .endif
4792    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4793
4794    and     r0, r0, r2                           @ optional op; may set condition codes
4795    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4796    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4797    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4798    GOTO_OPCODE(ip)                     @ jump to next instruction
4799    /* 14-17 instructions */
4800
4801
4802
4803/* ------------------------------ */
4804    .balign 64
4805.L_OP_OR_LONG: /* 0xa1 */
4806/* File: armv5te/OP_OR_LONG.S */
4807/* File: armv5te/binopWide.S */
4808    /*
4809     * Generic 64-bit binary operation.  Provide an "instr" line that
4810     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4811     * This could be an ARM instruction or a function call.  (If the result
4812     * comes back in a register other than r0, you can override "result".)
4813     *
4814     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4815     * vCC (r1).  Useful for integer division and modulus.
4816     *
4817     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4818     *      xor-long, add-double, sub-double, mul-double, div-double,
4819     *      rem-double
4820     *
4821     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4822     */
4823    /* binop vAA, vBB, vCC */
4824    FETCH(r0, 1)                        @ r0<- CCBB
4825    mov     r9, rINST, lsr #8           @ r9<- AA
4826    and     r2, r0, #255                @ r2<- BB
4827    mov     r3, r0, lsr #8              @ r3<- CC
4828    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4829    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4830    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4831    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4832    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4833    .if 0
4834    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4835    beq     common_errDivideByZero
4836    .endif
4837    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4838
4839    orr     r0, r0, r2                           @ optional op; may set condition codes
4840    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4842    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4843    GOTO_OPCODE(ip)                     @ jump to next instruction
4844    /* 14-17 instructions */
4845
4846
4847
4848/* ------------------------------ */
4849    .balign 64
4850.L_OP_XOR_LONG: /* 0xa2 */
4851/* File: armv5te/OP_XOR_LONG.S */
4852/* File: armv5te/binopWide.S */
4853    /*
4854     * Generic 64-bit binary operation.  Provide an "instr" line that
4855     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4856     * This could be an ARM instruction or a function call.  (If the result
4857     * comes back in a register other than r0, you can override "result".)
4858     *
4859     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4860     * vCC (r1).  Useful for integer division and modulus.
4861     *
4862     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4863     *      xor-long, add-double, sub-double, mul-double, div-double,
4864     *      rem-double
4865     *
4866     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4867     */
4868    /* binop vAA, vBB, vCC */
4869    FETCH(r0, 1)                        @ r0<- CCBB
4870    mov     r9, rINST, lsr #8           @ r9<- AA
4871    and     r2, r0, #255                @ r2<- BB
4872    mov     r3, r0, lsr #8              @ r3<- CC
4873    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4874    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4875    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4876    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4877    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4878    .if 0
4879    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4880    beq     common_errDivideByZero
4881    .endif
4882    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4883
4884    eor     r0, r0, r2                           @ optional op; may set condition codes
4885    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4887    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4888    GOTO_OPCODE(ip)                     @ jump to next instruction
4889    /* 14-17 instructions */
4890
4891
4892
4893/* ------------------------------ */
4894    .balign 64
4895.L_OP_SHL_LONG: /* 0xa3 */
4896/* File: armv5te/OP_SHL_LONG.S */
4897    /*
4898     * Long integer shift.  This is different from the generic 32/64-bit
4899     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4900     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4901     * 6 bits of the shift distance.
4902     */
4903    /* shl-long vAA, vBB, vCC */
4904    FETCH(r0, 1)                        @ r0<- CCBB
4905    mov     r9, rINST, lsr #8           @ r9<- AA
4906    and     r3, r0, #255                @ r3<- BB
4907    mov     r0, r0, lsr #8              @ r0<- CC
4908    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4909    GET_VREG(r2, r0)                    @ r2<- vCC
4910    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4911    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4912    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4913
4914    mov     r1, r1, asl r2              @  r1<- r1 << r2
4915    rsb     r3, r2, #32                 @  r3<- 32 - r2
4916    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4917    subs    ip, r2, #32                 @  ip<- r2 - 32
4918    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4919    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4920    b       .LOP_SHL_LONG_finish
4921
4922/* ------------------------------ */
4923    .balign 64
4924.L_OP_SHR_LONG: /* 0xa4 */
4925/* File: armv5te/OP_SHR_LONG.S */
4926    /*
4927     * Long integer shift.  This is different from the generic 32/64-bit
4928     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4929     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4930     * 6 bits of the shift distance.
4931     */
4932    /* shr-long vAA, vBB, vCC */
4933    FETCH(r0, 1)                        @ r0<- CCBB
4934    mov     r9, rINST, lsr #8           @ r9<- AA
4935    and     r3, r0, #255                @ r3<- BB
4936    mov     r0, r0, lsr #8              @ r0<- CC
4937    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4938    GET_VREG(r2, r0)                    @ r2<- vCC
4939    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4940    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4941    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4942
4943    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4944    rsb     r3, r2, #32                 @  r3<- 32 - r2
4945    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4946    subs    ip, r2, #32                 @  ip<- r2 - 32
4947    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4948    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4949    b       .LOP_SHR_LONG_finish
4950
4951/* ------------------------------ */
4952    .balign 64
4953.L_OP_USHR_LONG: /* 0xa5 */
4954/* File: armv5te/OP_USHR_LONG.S */
4955    /*
4956     * Long integer shift.  This is different from the generic 32/64-bit
4957     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4958     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4959     * 6 bits of the shift distance.
4960     */
4961    /* ushr-long vAA, vBB, vCC */
4962    FETCH(r0, 1)                        @ r0<- CCBB
4963    mov     r9, rINST, lsr #8           @ r9<- AA
4964    and     r3, r0, #255                @ r3<- BB
4965    mov     r0, r0, lsr #8              @ r0<- CC
4966    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4967    GET_VREG(r2, r0)                    @ r2<- vCC
4968    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4969    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4970    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4971
4972    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4973    rsb     r3, r2, #32                 @  r3<- 32 - r2
4974    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4975    subs    ip, r2, #32                 @  ip<- r2 - 32
4976    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4977    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4978    b       .LOP_USHR_LONG_finish
4979
4980/* ------------------------------ */
4981    .balign 64
4982.L_OP_ADD_FLOAT: /* 0xa6 */
4983/* File: arm-vfp/OP_ADD_FLOAT.S */
4984/* File: arm-vfp/fbinop.S */
4985    /*
4986     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4987     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4988     * use the "softfp" ABI, this must be an instruction, not a function call.
4989     *
4990     * For: add-float, sub-float, mul-float, div-float
4991     */
4992    /* floatop vAA, vBB, vCC */
4993    FETCH(r0, 1)                        @ r0<- CCBB
4994    mov     r9, rINST, lsr #8           @ r9<- AA
4995    mov     r3, r0, lsr #8              @ r3<- CC
4996    and     r2, r0, #255                @ r2<- BB
4997    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4998    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4999    flds    s1, [r3]                    @ s1<- vCC
5000    flds    s0, [r2]                    @ s0<- vBB
5001
5002    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5003    fadds   s2, s0, s1                              @ s2<- op
5004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5005    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5006    fsts    s2, [r9]                    @ vAA<- s2
5007    GOTO_OPCODE(ip)                     @ jump to next instruction
5008
5009
5010/* ------------------------------ */
5011    .balign 64
5012.L_OP_SUB_FLOAT: /* 0xa7 */
5013/* File: arm-vfp/OP_SUB_FLOAT.S */
5014/* File: arm-vfp/fbinop.S */
5015    /*
5016     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5017     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5018     * use the "softfp" ABI, this must be an instruction, not a function call.
5019     *
5020     * For: add-float, sub-float, mul-float, div-float
5021     */
5022    /* floatop vAA, vBB, vCC */
5023    FETCH(r0, 1)                        @ r0<- CCBB
5024    mov     r9, rINST, lsr #8           @ r9<- AA
5025    mov     r3, r0, lsr #8              @ r3<- CC
5026    and     r2, r0, #255                @ r2<- BB
5027    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5028    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5029    flds    s1, [r3]                    @ s1<- vCC
5030    flds    s0, [r2]                    @ s0<- vBB
5031
5032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5033    fsubs   s2, s0, s1                              @ s2<- op
5034    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5035    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5036    fsts    s2, [r9]                    @ vAA<- s2
5037    GOTO_OPCODE(ip)                     @ jump to next instruction
5038
5039
5040/* ------------------------------ */
5041    .balign 64
5042.L_OP_MUL_FLOAT: /* 0xa8 */
5043/* File: arm-vfp/OP_MUL_FLOAT.S */
5044/* File: arm-vfp/fbinop.S */
5045    /*
5046     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5047     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5048     * use the "softfp" ABI, this must be an instruction, not a function call.
5049     *
5050     * For: add-float, sub-float, mul-float, div-float
5051     */
5052    /* floatop vAA, vBB, vCC */
5053    FETCH(r0, 1)                        @ r0<- CCBB
5054    mov     r9, rINST, lsr #8           @ r9<- AA
5055    mov     r3, r0, lsr #8              @ r3<- CC
5056    and     r2, r0, #255                @ r2<- BB
5057    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5058    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5059    flds    s1, [r3]                    @ s1<- vCC
5060    flds    s0, [r2]                    @ s0<- vBB
5061
5062    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5063    fmuls   s2, s0, s1                              @ s2<- op
5064    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5065    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5066    fsts    s2, [r9]                    @ vAA<- s2
5067    GOTO_OPCODE(ip)                     @ jump to next instruction
5068
5069
5070/* ------------------------------ */
5071    .balign 64
5072.L_OP_DIV_FLOAT: /* 0xa9 */
5073/* File: arm-vfp/OP_DIV_FLOAT.S */
5074/* File: arm-vfp/fbinop.S */
5075    /*
5076     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5077     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5078     * use the "softfp" ABI, this must be an instruction, not a function call.
5079     *
5080     * For: add-float, sub-float, mul-float, div-float
5081     */
5082    /* floatop vAA, vBB, vCC */
5083    FETCH(r0, 1)                        @ r0<- CCBB
5084    mov     r9, rINST, lsr #8           @ r9<- AA
5085    mov     r3, r0, lsr #8              @ r3<- CC
5086    and     r2, r0, #255                @ r2<- BB
5087    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5088    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5089    flds    s1, [r3]                    @ s1<- vCC
5090    flds    s0, [r2]                    @ s0<- vBB
5091
5092    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5093    fdivs   s2, s0, s1                              @ s2<- op
5094    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5095    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5096    fsts    s2, [r9]                    @ vAA<- s2
5097    GOTO_OPCODE(ip)                     @ jump to next instruction
5098
5099
5100/* ------------------------------ */
5101    .balign 64
5102.L_OP_REM_FLOAT: /* 0xaa */
5103/* File: armv5te/OP_REM_FLOAT.S */
5104/* EABI doesn't define a float remainder function, but libm does */
5105/* File: armv5te/binop.S */
5106    /*
5107     * Generic 32-bit binary operation.  Provide an "instr" line that
5108     * specifies an instruction that performs "result = r0 op r1".
5109     * This could be an ARM instruction or a function call.  (If the result
5110     * comes back in a register other than r0, you can override "result".)
5111     *
5112     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5113     * vCC (r1).  Useful for integer division and modulus.  Note that we
5114     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5115     * handles it correctly.
5116     *
5117     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5118     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5119     *      mul-float, div-float, rem-float
5120     */
5121    /* binop vAA, vBB, vCC */
5122    FETCH(r0, 1)                        @ r0<- CCBB
5123    mov     r9, rINST, lsr #8           @ r9<- AA
5124    mov     r3, r0, lsr #8              @ r3<- CC
5125    and     r2, r0, #255                @ r2<- BB
5126    GET_VREG(r1, r3)                    @ r1<- vCC
5127    GET_VREG(r0, r2)                    @ r0<- vBB
5128    .if 0
5129    cmp     r1, #0                      @ is second operand zero?
5130    beq     common_errDivideByZero
5131    .endif
5132
5133    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5134                               @ optional op; may set condition codes
5135    bl      fmodf                              @ r0<- op, r0-r3 changed
5136    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5137    SET_VREG(r0, r9)               @ vAA<- r0
5138    GOTO_OPCODE(ip)                     @ jump to next instruction
5139    /* 11-14 instructions */
5140
5141
5142
5143/* ------------------------------ */
5144    .balign 64
5145.L_OP_ADD_DOUBLE: /* 0xab */
5146/* File: arm-vfp/OP_ADD_DOUBLE.S */
5147/* File: arm-vfp/fbinopWide.S */
5148    /*
5149     * Generic 64-bit double-precision floating point binary operation.
5150     * Provide an "instr" line that specifies an instruction that performs
5151     * "d2 = d0 op d1".
5152     *
5153     * for: add-double, sub-double, mul-double, div-double
5154     */
5155    /* doubleop vAA, vBB, vCC */
5156    FETCH(r0, 1)                        @ r0<- CCBB
5157    mov     r9, rINST, lsr #8           @ r9<- AA
5158    mov     r3, r0, lsr #8              @ r3<- CC
5159    and     r2, r0, #255                @ r2<- BB
5160    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5161    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5162    fldd    d1, [r3]                    @ d1<- vCC
5163    fldd    d0, [r2]                    @ d0<- vBB
5164
5165    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5166    faddd   d2, d0, d1                              @ s2<- op
5167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5168    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5169    fstd    d2, [r9]                    @ vAA<- d2
5170    GOTO_OPCODE(ip)                     @ jump to next instruction
5171
5172
5173/* ------------------------------ */
5174    .balign 64
5175.L_OP_SUB_DOUBLE: /* 0xac */
5176/* File: arm-vfp/OP_SUB_DOUBLE.S */
5177/* File: arm-vfp/fbinopWide.S */
5178    /*
5179     * Generic 64-bit double-precision floating point binary operation.
5180     * Provide an "instr" line that specifies an instruction that performs
5181     * "d2 = d0 op d1".
5182     *
5183     * for: add-double, sub-double, mul-double, div-double
5184     */
5185    /* doubleop vAA, vBB, vCC */
5186    FETCH(r0, 1)                        @ r0<- CCBB
5187    mov     r9, rINST, lsr #8           @ r9<- AA
5188    mov     r3, r0, lsr #8              @ r3<- CC
5189    and     r2, r0, #255                @ r2<- BB
5190    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5191    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5192    fldd    d1, [r3]                    @ d1<- vCC
5193    fldd    d0, [r2]                    @ d0<- vBB
5194
5195    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5196    fsubd   d2, d0, d1                              @ s2<- op
5197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5198    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5199    fstd    d2, [r9]                    @ vAA<- d2
5200    GOTO_OPCODE(ip)                     @ jump to next instruction
5201
5202
5203/* ------------------------------ */
5204    .balign 64
5205.L_OP_MUL_DOUBLE: /* 0xad */
5206/* File: arm-vfp/OP_MUL_DOUBLE.S */
5207/* File: arm-vfp/fbinopWide.S */
5208    /*
5209     * Generic 64-bit double-precision floating point binary operation.
5210     * Provide an "instr" line that specifies an instruction that performs
5211     * "d2 = d0 op d1".
5212     *
5213     * for: add-double, sub-double, mul-double, div-double
5214     */
5215    /* doubleop vAA, vBB, vCC */
5216    FETCH(r0, 1)                        @ r0<- CCBB
5217    mov     r9, rINST, lsr #8           @ r9<- AA
5218    mov     r3, r0, lsr #8              @ r3<- CC
5219    and     r2, r0, #255                @ r2<- BB
5220    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5221    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5222    fldd    d1, [r3]                    @ d1<- vCC
5223    fldd    d0, [r2]                    @ d0<- vBB
5224
5225    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5226    fmuld   d2, d0, d1                              @ s2<- op
5227    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5228    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5229    fstd    d2, [r9]                    @ vAA<- d2
5230    GOTO_OPCODE(ip)                     @ jump to next instruction
5231
5232
5233/* ------------------------------ */
5234    .balign 64
5235.L_OP_DIV_DOUBLE: /* 0xae */
5236/* File: arm-vfp/OP_DIV_DOUBLE.S */
5237/* File: arm-vfp/fbinopWide.S */
5238    /*
5239     * Generic 64-bit double-precision floating point binary operation.
5240     * Provide an "instr" line that specifies an instruction that performs
5241     * "d2 = d0 op d1".
5242     *
5243     * for: add-double, sub-double, mul-double, div-double
5244     */
5245    /* doubleop vAA, vBB, vCC */
5246    FETCH(r0, 1)                        @ r0<- CCBB
5247    mov     r9, rINST, lsr #8           @ r9<- AA
5248    mov     r3, r0, lsr #8              @ r3<- CC
5249    and     r2, r0, #255                @ r2<- BB
5250    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5251    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5252    fldd    d1, [r3]                    @ d1<- vCC
5253    fldd    d0, [r2]                    @ d0<- vBB
5254
5255    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5256    fdivd   d2, d0, d1                              @ s2<- op
5257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5258    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5259    fstd    d2, [r9]                    @ vAA<- d2
5260    GOTO_OPCODE(ip)                     @ jump to next instruction
5261
5262
5263/* ------------------------------ */
5264    .balign 64
5265.L_OP_REM_DOUBLE: /* 0xaf */
5266/* File: armv5te/OP_REM_DOUBLE.S */
5267/* EABI doesn't define a double remainder function, but libm does */
5268/* File: armv5te/binopWide.S */
5269    /*
5270     * Generic 64-bit binary operation.  Provide an "instr" line that
5271     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5272     * This could be an ARM instruction or a function call.  (If the result
5273     * comes back in a register other than r0, you can override "result".)
5274     *
5275     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5276     * vCC (r1).  Useful for integer division and modulus.
5277     *
5278     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5279     *      xor-long, add-double, sub-double, mul-double, div-double,
5280     *      rem-double
5281     *
5282     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5283     */
5284    /* binop vAA, vBB, vCC */
5285    FETCH(r0, 1)                        @ r0<- CCBB
5286    mov     r9, rINST, lsr #8           @ r9<- AA
5287    and     r2, r0, #255                @ r2<- BB
5288    mov     r3, r0, lsr #8              @ r3<- CC
5289    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5290    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5291    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5292    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5293    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5294    .if 0
5295    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5296    beq     common_errDivideByZero
5297    .endif
5298    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5299
5300                               @ optional op; may set condition codes
5301    bl      fmod                              @ result<- op, r0-r3 changed
5302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5303    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5304    GOTO_OPCODE(ip)                     @ jump to next instruction
5305    /* 14-17 instructions */
5306
5307
5308
5309/* ------------------------------ */
5310    .balign 64
5311.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5312/* File: armv5te/OP_ADD_INT_2ADDR.S */
5313/* File: armv5te/binop2addr.S */
5314    /*
5315     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5316     * that specifies an instruction that performs "result = r0 op r1".
5317     * This could be an ARM instruction or a function call.  (If the result
5318     * comes back in a register other than r0, you can override "result".)
5319     *
5320     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5321     * vCC (r1).  Useful for integer division and modulus.
5322     *
5323     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5324     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5325     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5326     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5327     */
5328    /* binop/2addr vA, vB */
5329    mov     r9, rINST, lsr #8           @ r9<- A+
5330    mov     r3, rINST, lsr #12          @ r3<- B
5331    and     r9, r9, #15
5332    GET_VREG(r1, r3)                    @ r1<- vB
5333    GET_VREG(r0, r9)                    @ r0<- vA
5334    .if 0
5335    cmp     r1, #0                      @ is second operand zero?
5336    beq     common_errDivideByZero
5337    .endif
5338    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5339
5340                               @ optional op; may set condition codes
5341    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5342    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5343    SET_VREG(r0, r9)               @ vAA<- r0
5344    GOTO_OPCODE(ip)                     @ jump to next instruction
5345    /* 10-13 instructions */
5346
5347
5348
5349/* ------------------------------ */
5350    .balign 64
5351.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5352/* File: armv5te/OP_SUB_INT_2ADDR.S */
5353/* File: armv5te/binop2addr.S */
5354    /*
5355     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5356     * that specifies an instruction that performs "result = r0 op r1".
5357     * This could be an ARM instruction or a function call.  (If the result
5358     * comes back in a register other than r0, you can override "result".)
5359     *
5360     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5361     * vCC (r1).  Useful for integer division and modulus.
5362     *
5363     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5364     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5365     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5366     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5367     */
5368    /* binop/2addr vA, vB */
5369    mov     r9, rINST, lsr #8           @ r9<- A+
5370    mov     r3, rINST, lsr #12          @ r3<- B
5371    and     r9, r9, #15
5372    GET_VREG(r1, r3)                    @ r1<- vB
5373    GET_VREG(r0, r9)                    @ r0<- vA
5374    .if 0
5375    cmp     r1, #0                      @ is second operand zero?
5376    beq     common_errDivideByZero
5377    .endif
5378    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5379
5380                               @ optional op; may set condition codes
5381    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5382    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5383    SET_VREG(r0, r9)               @ vAA<- r0
5384    GOTO_OPCODE(ip)                     @ jump to next instruction
5385    /* 10-13 instructions */
5386
5387
5388
5389/* ------------------------------ */
5390    .balign 64
5391.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5392/* File: armv5te/OP_MUL_INT_2ADDR.S */
5393/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5394/* File: armv5te/binop2addr.S */
5395    /*
5396     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5397     * that specifies an instruction that performs "result = r0 op r1".
5398     * This could be an ARM instruction or a function call.  (If the result
5399     * comes back in a register other than r0, you can override "result".)
5400     *
5401     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5402     * vCC (r1).  Useful for integer division and modulus.
5403     *
5404     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5405     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5406     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5407     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5408     */
5409    /* binop/2addr vA, vB */
5410    mov     r9, rINST, lsr #8           @ r9<- A+
5411    mov     r3, rINST, lsr #12          @ r3<- B
5412    and     r9, r9, #15
5413    GET_VREG(r1, r3)                    @ r1<- vB
5414    GET_VREG(r0, r9)                    @ r0<- vA
5415    .if 0
5416    cmp     r1, #0                      @ is second operand zero?
5417    beq     common_errDivideByZero
5418    .endif
5419    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5420
5421                               @ optional op; may set condition codes
5422    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5423    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5424    SET_VREG(r0, r9)               @ vAA<- r0
5425    GOTO_OPCODE(ip)                     @ jump to next instruction
5426    /* 10-13 instructions */
5427
5428
5429
5430/* ------------------------------ */
5431    .balign 64
5432.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5433/* File: armv5te/OP_DIV_INT_2ADDR.S */
5434/* File: armv5te/binop2addr.S */
5435    /*
5436     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5437     * that specifies an instruction that performs "result = r0 op r1".
5438     * This could be an ARM instruction or a function call.  (If the result
5439     * comes back in a register other than r0, you can override "result".)
5440     *
5441     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5442     * vCC (r1).  Useful for integer division and modulus.
5443     *
5444     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5445     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5446     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5447     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5448     */
5449    /* binop/2addr vA, vB */
5450    mov     r9, rINST, lsr #8           @ r9<- A+
5451    mov     r3, rINST, lsr #12          @ r3<- B
5452    and     r9, r9, #15
5453    GET_VREG(r1, r3)                    @ r1<- vB
5454    GET_VREG(r0, r9)                    @ r0<- vA
5455    .if 1
5456    cmp     r1, #0                      @ is second operand zero?
5457    beq     common_errDivideByZero
5458    .endif
5459    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5460
5461                               @ optional op; may set condition codes
5462    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5463    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5464    SET_VREG(r0, r9)               @ vAA<- r0
5465    GOTO_OPCODE(ip)                     @ jump to next instruction
5466    /* 10-13 instructions */
5467
5468
5469
5470/* ------------------------------ */
5471    .balign 64
5472.L_OP_REM_INT_2ADDR: /* 0xb4 */
5473/* File: armv5te/OP_REM_INT_2ADDR.S */
5474/* idivmod returns quotient in r0 and remainder in r1 */
5475/* File: armv5te/binop2addr.S */
5476    /*
5477     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5478     * that specifies an instruction that performs "result = r0 op r1".
5479     * This could be an ARM instruction or a function call.  (If the result
5480     * comes back in a register other than r0, you can override "result".)
5481     *
5482     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5483     * vCC (r1).  Useful for integer division and modulus.
5484     *
5485     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5486     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5487     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5488     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5489     */
5490    /* binop/2addr vA, vB */
5491    mov     r9, rINST, lsr #8           @ r9<- A+
5492    mov     r3, rINST, lsr #12          @ r3<- B
5493    and     r9, r9, #15
5494    GET_VREG(r1, r3)                    @ r1<- vB
5495    GET_VREG(r0, r9)                    @ r0<- vA
5496    .if 1
5497    cmp     r1, #0                      @ is second operand zero?
5498    beq     common_errDivideByZero
5499    .endif
5500    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5501
5502                               @ optional op; may set condition codes
5503    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5504    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5505    SET_VREG(r1, r9)               @ vAA<- r1
5506    GOTO_OPCODE(ip)                     @ jump to next instruction
5507    /* 10-13 instructions */
5508
5509
5510
5511/* ------------------------------ */
5512    .balign 64
5513.L_OP_AND_INT_2ADDR: /* 0xb5 */
5514/* File: armv5te/OP_AND_INT_2ADDR.S */
5515/* File: armv5te/binop2addr.S */
5516    /*
5517     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5518     * that specifies an instruction that performs "result = r0 op r1".
5519     * This could be an ARM instruction or a function call.  (If the result
5520     * comes back in a register other than r0, you can override "result".)
5521     *
5522     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5523     * vCC (r1).  Useful for integer division and modulus.
5524     *
5525     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5526     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5527     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5528     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5529     */
5530    /* binop/2addr vA, vB */
5531    mov     r9, rINST, lsr #8           @ r9<- A+
5532    mov     r3, rINST, lsr #12          @ r3<- B
5533    and     r9, r9, #15
5534    GET_VREG(r1, r3)                    @ r1<- vB
5535    GET_VREG(r0, r9)                    @ r0<- vA
5536    .if 0
5537    cmp     r1, #0                      @ is second operand zero?
5538    beq     common_errDivideByZero
5539    .endif
5540    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5541
5542                               @ optional op; may set condition codes
5543    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5544    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5545    SET_VREG(r0, r9)               @ vAA<- r0
5546    GOTO_OPCODE(ip)                     @ jump to next instruction
5547    /* 10-13 instructions */
5548
5549
5550
5551/* ------------------------------ */
5552    .balign 64
5553.L_OP_OR_INT_2ADDR: /* 0xb6 */
5554/* File: armv5te/OP_OR_INT_2ADDR.S */
5555/* File: armv5te/binop2addr.S */
5556    /*
5557     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5558     * that specifies an instruction that performs "result = r0 op r1".
5559     * This could be an ARM instruction or a function call.  (If the result
5560     * comes back in a register other than r0, you can override "result".)
5561     *
5562     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5563     * vCC (r1).  Useful for integer division and modulus.
5564     *
5565     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5566     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5567     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5568     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5569     */
5570    /* binop/2addr vA, vB */
5571    mov     r9, rINST, lsr #8           @ r9<- A+
5572    mov     r3, rINST, lsr #12          @ r3<- B
5573    and     r9, r9, #15
5574    GET_VREG(r1, r3)                    @ r1<- vB
5575    GET_VREG(r0, r9)                    @ r0<- vA
5576    .if 0
5577    cmp     r1, #0                      @ is second operand zero?
5578    beq     common_errDivideByZero
5579    .endif
5580    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5581
5582                               @ optional op; may set condition codes
5583    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5584    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5585    SET_VREG(r0, r9)               @ vAA<- r0
5586    GOTO_OPCODE(ip)                     @ jump to next instruction
5587    /* 10-13 instructions */
5588
5589
5590
5591/* ------------------------------ */
5592    .balign 64
5593.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5594/* File: armv5te/OP_XOR_INT_2ADDR.S */
5595/* File: armv5te/binop2addr.S */
5596    /*
5597     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5598     * that specifies an instruction that performs "result = r0 op r1".
5599     * This could be an ARM instruction or a function call.  (If the result
5600     * comes back in a register other than r0, you can override "result".)
5601     *
5602     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5603     * vCC (r1).  Useful for integer division and modulus.
5604     *
5605     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5606     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5607     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5608     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5609     */
5610    /* binop/2addr vA, vB */
5611    mov     r9, rINST, lsr #8           @ r9<- A+
5612    mov     r3, rINST, lsr #12          @ r3<- B
5613    and     r9, r9, #15
5614    GET_VREG(r1, r3)                    @ r1<- vB
5615    GET_VREG(r0, r9)                    @ r0<- vA
5616    .if 0
5617    cmp     r1, #0                      @ is second operand zero?
5618    beq     common_errDivideByZero
5619    .endif
5620    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5621
5622                               @ optional op; may set condition codes
5623    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5625    SET_VREG(r0, r9)               @ vAA<- r0
5626    GOTO_OPCODE(ip)                     @ jump to next instruction
5627    /* 10-13 instructions */
5628
5629
5630
5631/* ------------------------------ */
5632    .balign 64
5633.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5634/* File: armv5te/OP_SHL_INT_2ADDR.S */
5635/* File: armv5te/binop2addr.S */
5636    /*
5637     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5638     * that specifies an instruction that performs "result = r0 op r1".
5639     * This could be an ARM instruction or a function call.  (If the result
5640     * comes back in a register other than r0, you can override "result".)
5641     *
5642     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5643     * vCC (r1).  Useful for integer division and modulus.
5644     *
5645     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5646     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5647     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5648     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5649     */
5650    /* binop/2addr vA, vB */
5651    mov     r9, rINST, lsr #8           @ r9<- A+
5652    mov     r3, rINST, lsr #12          @ r3<- B
5653    and     r9, r9, #15
5654    GET_VREG(r1, r3)                    @ r1<- vB
5655    GET_VREG(r0, r9)                    @ r0<- vA
5656    .if 0
5657    cmp     r1, #0                      @ is second operand zero?
5658    beq     common_errDivideByZero
5659    .endif
5660    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5661
5662    and     r1, r1, #31                           @ optional op; may set condition codes
5663    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5664    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5665    SET_VREG(r0, r9)               @ vAA<- r0
5666    GOTO_OPCODE(ip)                     @ jump to next instruction
5667    /* 10-13 instructions */
5668
5669
5670
5671/* ------------------------------ */
5672    .balign 64
5673.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5674/* File: armv5te/OP_SHR_INT_2ADDR.S */
5675/* File: armv5te/binop2addr.S */
5676    /*
5677     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5678     * that specifies an instruction that performs "result = r0 op r1".
5679     * This could be an ARM instruction or a function call.  (If the result
5680     * comes back in a register other than r0, you can override "result".)
5681     *
5682     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5683     * vCC (r1).  Useful for integer division and modulus.
5684     *
5685     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5686     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5687     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5688     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5689     */
5690    /* binop/2addr vA, vB */
5691    mov     r9, rINST, lsr #8           @ r9<- A+
5692    mov     r3, rINST, lsr #12          @ r3<- B
5693    and     r9, r9, #15
5694    GET_VREG(r1, r3)                    @ r1<- vB
5695    GET_VREG(r0, r9)                    @ r0<- vA
5696    .if 0
5697    cmp     r1, #0                      @ is second operand zero?
5698    beq     common_errDivideByZero
5699    .endif
5700    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5701
5702    and     r1, r1, #31                           @ optional op; may set condition codes
5703    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5704    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5705    SET_VREG(r0, r9)               @ vAA<- r0
5706    GOTO_OPCODE(ip)                     @ jump to next instruction
5707    /* 10-13 instructions */
5708
5709
5710
5711/* ------------------------------ */
5712    .balign 64
5713.L_OP_USHR_INT_2ADDR: /* 0xba */
5714/* File: armv5te/OP_USHR_INT_2ADDR.S */
5715/* File: armv5te/binop2addr.S */
5716    /*
5717     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5718     * that specifies an instruction that performs "result = r0 op r1".
5719     * This could be an ARM instruction or a function call.  (If the result
5720     * comes back in a register other than r0, you can override "result".)
5721     *
5722     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5723     * vCC (r1).  Useful for integer division and modulus.
5724     *
5725     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5726     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5727     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5728     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5729     */
5730    /* binop/2addr vA, vB */
5731    mov     r9, rINST, lsr #8           @ r9<- A+
5732    mov     r3, rINST, lsr #12          @ r3<- B
5733    and     r9, r9, #15
5734    GET_VREG(r1, r3)                    @ r1<- vB
5735    GET_VREG(r0, r9)                    @ r0<- vA
5736    .if 0
5737    cmp     r1, #0                      @ is second operand zero?
5738    beq     common_errDivideByZero
5739    .endif
5740    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5741
5742    and     r1, r1, #31                           @ optional op; may set condition codes
5743    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5744    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5745    SET_VREG(r0, r9)               @ vAA<- r0
5746    GOTO_OPCODE(ip)                     @ jump to next instruction
5747    /* 10-13 instructions */
5748
5749
5750
5751/* ------------------------------ */
5752    .balign 64
5753.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5754/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5755/* File: armv5te/binopWide2addr.S */
5756    /*
5757     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5758     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5759     * This could be an ARM instruction or a function call.  (If the result
5760     * comes back in a register other than r0, you can override "result".)
5761     *
5762     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5763     * vCC (r1).  Useful for integer division and modulus.
5764     *
5765     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5766     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5767     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5768     *      rem-double/2addr
5769     */
5770    /* binop/2addr vA, vB */
5771    mov     r9, rINST, lsr #8           @ r9<- A+
5772    mov     r1, rINST, lsr #12          @ r1<- B
5773    and     r9, r9, #15
5774    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5775    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5776    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5777    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5778    .if 0
5779    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5780    beq     common_errDivideByZero
5781    .endif
5782    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5783
5784    adds    r0, r0, r2                           @ optional op; may set condition codes
5785    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5786    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5787    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5788    GOTO_OPCODE(ip)                     @ jump to next instruction
5789    /* 12-15 instructions */
5790
5791
5792
5793/* ------------------------------ */
5794    .balign 64
5795.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5796/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5797/* File: armv5te/binopWide2addr.S */
5798    /*
5799     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5800     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5801     * This could be an ARM instruction or a function call.  (If the result
5802     * comes back in a register other than r0, you can override "result".)
5803     *
5804     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5805     * vCC (r1).  Useful for integer division and modulus.
5806     *
5807     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5808     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5809     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5810     *      rem-double/2addr
5811     */
5812    /* binop/2addr vA, vB */
5813    mov     r9, rINST, lsr #8           @ r9<- A+
5814    mov     r1, rINST, lsr #12          @ r1<- B
5815    and     r9, r9, #15
5816    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5817    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5818    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5819    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5820    .if 0
5821    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5822    beq     common_errDivideByZero
5823    .endif
5824    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5825
5826    subs    r0, r0, r2                           @ optional op; may set condition codes
5827    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5829    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5830    GOTO_OPCODE(ip)                     @ jump to next instruction
5831    /* 12-15 instructions */
5832
5833
5834
5835/* ------------------------------ */
5836    .balign 64
5837.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5838/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5839    /*
5840     * Signed 64-bit integer multiply, "/2addr" version.
5841     *
5842     * See OP_MUL_LONG for an explanation.
5843     *
5844     * We get a little tight on registers, so to avoid looking up &fp[A]
5845     * again we stuff it into rINST.
5846     */
5847    /* mul-long/2addr vA, vB */
5848    mov     r9, rINST, lsr #8           @ r9<- A+
5849    mov     r1, rINST, lsr #12          @ r1<- B
5850    and     r9, r9, #15
5851    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5852    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5853    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5854    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5855    mul     ip, r2, r1                  @  ip<- ZxW
5856    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5857    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5858    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5859    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5860    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5861    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5862    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5863    GOTO_OPCODE(ip)                     @ jump to next instruction
5864
5865
5866/* ------------------------------ */
5867    .balign 64
5868.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5869/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5870/* File: armv5te/binopWide2addr.S */
5871    /*
5872     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5873     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5874     * This could be an ARM instruction or a function call.  (If the result
5875     * comes back in a register other than r0, you can override "result".)
5876     *
5877     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5878     * vCC (r1).  Useful for integer division and modulus.
5879     *
5880     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5881     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5882     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5883     *      rem-double/2addr
5884     */
5885    /* binop/2addr vA, vB */
5886    mov     r9, rINST, lsr #8           @ r9<- A+
5887    mov     r1, rINST, lsr #12          @ r1<- B
5888    and     r9, r9, #15
5889    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5890    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5891    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5892    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5893    .if 1
5894    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5895    beq     common_errDivideByZero
5896    .endif
5897    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5898
5899                               @ optional op; may set condition codes
5900    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5901    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5902    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5903    GOTO_OPCODE(ip)                     @ jump to next instruction
5904    /* 12-15 instructions */
5905
5906
5907
5908/* ------------------------------ */
5909    .balign 64
5910.L_OP_REM_LONG_2ADDR: /* 0xbf */
5911/* File: armv5te/OP_REM_LONG_2ADDR.S */
5912/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5913/* File: armv5te/binopWide2addr.S */
5914    /*
5915     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5916     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5917     * This could be an ARM instruction or a function call.  (If the result
5918     * comes back in a register other than r0, you can override "result".)
5919     *
5920     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5921     * vCC (r1).  Useful for integer division and modulus.
5922     *
5923     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5924     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5925     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5926     *      rem-double/2addr
5927     */
5928    /* binop/2addr vA, vB */
5929    mov     r9, rINST, lsr #8           @ r9<- A+
5930    mov     r1, rINST, lsr #12          @ r1<- B
5931    and     r9, r9, #15
5932    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5933    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5934    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5935    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5936    .if 1
5937    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5938    beq     common_errDivideByZero
5939    .endif
5940    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5941
5942                               @ optional op; may set condition codes
5943    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5944    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5945    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5946    GOTO_OPCODE(ip)                     @ jump to next instruction
5947    /* 12-15 instructions */
5948
5949
5950
5951/* ------------------------------ */
5952    .balign 64
5953.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5954/* File: armv5te/OP_AND_LONG_2ADDR.S */
5955/* File: armv5te/binopWide2addr.S */
5956    /*
5957     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5958     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5959     * This could be an ARM instruction or a function call.  (If the result
5960     * comes back in a register other than r0, you can override "result".)
5961     *
5962     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5963     * vCC (r1).  Useful for integer division and modulus.
5964     *
5965     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5966     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5967     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5968     *      rem-double/2addr
5969     */
5970    /* binop/2addr vA, vB */
5971    mov     r9, rINST, lsr #8           @ r9<- A+
5972    mov     r1, rINST, lsr #12          @ r1<- B
5973    and     r9, r9, #15
5974    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5975    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5976    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5977    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5978    .if 0
5979    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5980    beq     common_errDivideByZero
5981    .endif
5982    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5983
5984    and     r0, r0, r2                           @ optional op; may set condition codes
5985    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5987    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5988    GOTO_OPCODE(ip)                     @ jump to next instruction
5989    /* 12-15 instructions */
5990
5991
5992
5993/* ------------------------------ */
5994    .balign 64
5995.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5996/* File: armv5te/OP_OR_LONG_2ADDR.S */
5997/* File: armv5te/binopWide2addr.S */
5998    /*
5999     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6000     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6001     * This could be an ARM instruction or a function call.  (If the result
6002     * comes back in a register other than r0, you can override "result".)
6003     *
6004     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6005     * vCC (r1).  Useful for integer division and modulus.
6006     *
6007     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6008     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6009     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6010     *      rem-double/2addr
6011     */
6012    /* binop/2addr vA, vB */
6013    mov     r9, rINST, lsr #8           @ r9<- A+
6014    mov     r1, rINST, lsr #12          @ r1<- B
6015    and     r9, r9, #15
6016    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6017    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6018    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6019    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6020    .if 0
6021    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6022    beq     common_errDivideByZero
6023    .endif
6024    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6025
6026    orr     r0, r0, r2                           @ optional op; may set condition codes
6027    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6028    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6029    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6030    GOTO_OPCODE(ip)                     @ jump to next instruction
6031    /* 12-15 instructions */
6032
6033
6034
6035/* ------------------------------ */
6036    .balign 64
6037.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6038/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6039/* File: armv5te/binopWide2addr.S */
6040    /*
6041     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6042     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6043     * This could be an ARM instruction or a function call.  (If the result
6044     * comes back in a register other than r0, you can override "result".)
6045     *
6046     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6047     * vCC (r1).  Useful for integer division and modulus.
6048     *
6049     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6050     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6051     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6052     *      rem-double/2addr
6053     */
6054    /* binop/2addr vA, vB */
6055    mov     r9, rINST, lsr #8           @ r9<- A+
6056    mov     r1, rINST, lsr #12          @ r1<- B
6057    and     r9, r9, #15
6058    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6059    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6060    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6061    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6062    .if 0
6063    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6064    beq     common_errDivideByZero
6065    .endif
6066    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6067
6068    eor     r0, r0, r2                           @ optional op; may set condition codes
6069    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6070    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6071    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6072    GOTO_OPCODE(ip)                     @ jump to next instruction
6073    /* 12-15 instructions */
6074
6075
6076
6077/* ------------------------------ */
6078    .balign 64
6079.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6080/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6081    /*
6082     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6083     * 32-bit shift distance.
6084     */
6085    /* shl-long/2addr vA, vB */
6086    mov     r9, rINST, lsr #8           @ r9<- A+
6087    mov     r3, rINST, lsr #12          @ r3<- B
6088    and     r9, r9, #15
6089    GET_VREG(r2, r3)                    @ r2<- vB
6090    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6091    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6092    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6093
6094    mov     r1, r1, asl r2              @  r1<- r1 << r2
6095    rsb     r3, r2, #32                 @  r3<- 32 - r2
6096    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6097    subs    ip, r2, #32                 @  ip<- r2 - 32
6098    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6099    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6100    mov     r0, r0, asl r2              @  r0<- r0 << r2
6101    b       .LOP_SHL_LONG_2ADDR_finish
6102
6103/* ------------------------------ */
6104    .balign 64
6105.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6106/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6107    /*
6108     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6109     * 32-bit shift distance.
6110     */
6111    /* shr-long/2addr vA, vB */
6112    mov     r9, rINST, lsr #8           @ r9<- A+
6113    mov     r3, rINST, lsr #12          @ r3<- B
6114    and     r9, r9, #15
6115    GET_VREG(r2, r3)                    @ r2<- vB
6116    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6117    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6118    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6119
6120    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6121    rsb     r3, r2, #32                 @  r3<- 32 - r2
6122    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6123    subs    ip, r2, #32                 @  ip<- r2 - 32
6124    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6125    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6126    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6127    b       .LOP_SHR_LONG_2ADDR_finish
6128
6129/* ------------------------------ */
6130    .balign 64
6131.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6132/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6133    /*
6134     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6135     * 32-bit shift distance.
6136     */
6137    /* ushr-long/2addr vA, vB */
6138    mov     r9, rINST, lsr #8           @ r9<- A+
6139    mov     r3, rINST, lsr #12          @ r3<- B
6140    and     r9, r9, #15
6141    GET_VREG(r2, r3)                    @ r2<- vB
6142    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6143    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6144    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6145
6146    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6147    rsb     r3, r2, #32                 @  r3<- 32 - r2
6148    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6149    subs    ip, r2, #32                 @  ip<- r2 - 32
6150    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6151    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6152    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6153    b       .LOP_USHR_LONG_2ADDR_finish
6154
6155/* ------------------------------ */
6156    .balign 64
6157.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6158/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6159/* File: arm-vfp/fbinop2addr.S */
6160    /*
6161     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6162     * an "instr" line that specifies an instruction that performs
6163     * "s2 = s0 op s1".
6164     *
6165     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6166     */
6167    /* binop/2addr vA, vB */
6168    mov     r3, rINST, lsr #12          @ r3<- B
6169    mov     r9, rINST, lsr #8           @ r9<- A+
6170    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6171    and     r9, r9, #15                 @ r9<- A
6172    flds    s1, [r3]                    @ s1<- vB
6173    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6174    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6175    flds    s0, [r9]                    @ s0<- vA
6176
6177    fadds   s2, s0, s1                              @ s2<- op
6178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6179    fsts    s2, [r9]                    @ vAA<- s2
6180    GOTO_OPCODE(ip)                     @ jump to next instruction
6181
6182
6183/* ------------------------------ */
6184    .balign 64
6185.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6186/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6187/* File: arm-vfp/fbinop2addr.S */
6188    /*
6189     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6190     * an "instr" line that specifies an instruction that performs
6191     * "s2 = s0 op s1".
6192     *
6193     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6194     */
6195    /* binop/2addr vA, vB */
6196    mov     r3, rINST, lsr #12          @ r3<- B
6197    mov     r9, rINST, lsr #8           @ r9<- A+
6198    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6199    and     r9, r9, #15                 @ r9<- A
6200    flds    s1, [r3]                    @ s1<- vB
6201    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6202    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6203    flds    s0, [r9]                    @ s0<- vA
6204
6205    fsubs   s2, s0, s1                              @ s2<- op
6206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6207    fsts    s2, [r9]                    @ vAA<- s2
6208    GOTO_OPCODE(ip)                     @ jump to next instruction
6209
6210
6211/* ------------------------------ */
6212    .balign 64
6213.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6214/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6215/* File: arm-vfp/fbinop2addr.S */
6216    /*
6217     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6218     * an "instr" line that specifies an instruction that performs
6219     * "s2 = s0 op s1".
6220     *
6221     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6222     */
6223    /* binop/2addr vA, vB */
6224    mov     r3, rINST, lsr #12          @ r3<- B
6225    mov     r9, rINST, lsr #8           @ r9<- A+
6226    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6227    and     r9, r9, #15                 @ r9<- A
6228    flds    s1, [r3]                    @ s1<- vB
6229    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6230    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6231    flds    s0, [r9]                    @ s0<- vA
6232
6233    fmuls   s2, s0, s1                              @ s2<- op
6234    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6235    fsts    s2, [r9]                    @ vAA<- s2
6236    GOTO_OPCODE(ip)                     @ jump to next instruction
6237
6238
6239/* ------------------------------ */
6240    .balign 64
6241.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6242/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6243/* File: arm-vfp/fbinop2addr.S */
6244    /*
6245     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6246     * an "instr" line that specifies an instruction that performs
6247     * "s2 = s0 op s1".
6248     *
6249     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6250     */
6251    /* binop/2addr vA, vB */
6252    mov     r3, rINST, lsr #12          @ r3<- B
6253    mov     r9, rINST, lsr #8           @ r9<- A+
6254    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6255    and     r9, r9, #15                 @ r9<- A
6256    flds    s1, [r3]                    @ s1<- vB
6257    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6258    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6259    flds    s0, [r9]                    @ s0<- vA
6260
6261    fdivs   s2, s0, s1                              @ s2<- op
6262    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6263    fsts    s2, [r9]                    @ vAA<- s2
6264    GOTO_OPCODE(ip)                     @ jump to next instruction
6265
6266
6267/* ------------------------------ */
6268    .balign 64
6269.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6270/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6271/* EABI doesn't define a float remainder function, but libm does */
6272/* File: armv5te/binop2addr.S */
6273    /*
6274     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6275     * that specifies an instruction that performs "result = r0 op r1".
6276     * This could be an ARM instruction or a function call.  (If the result
6277     * comes back in a register other than r0, you can override "result".)
6278     *
6279     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6280     * vCC (r1).  Useful for integer division and modulus.
6281     *
6282     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6283     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6284     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6285     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6286     */
6287    /* binop/2addr vA, vB */
6288    mov     r9, rINST, lsr #8           @ r9<- A+
6289    mov     r3, rINST, lsr #12          @ r3<- B
6290    and     r9, r9, #15
6291    GET_VREG(r1, r3)                    @ r1<- vB
6292    GET_VREG(r0, r9)                    @ r0<- vA
6293    .if 0
6294    cmp     r1, #0                      @ is second operand zero?
6295    beq     common_errDivideByZero
6296    .endif
6297    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6298
6299                               @ optional op; may set condition codes
6300    bl      fmodf                              @ r0<- op, r0-r3 changed
6301    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6302    SET_VREG(r0, r9)               @ vAA<- r0
6303    GOTO_OPCODE(ip)                     @ jump to next instruction
6304    /* 10-13 instructions */
6305
6306
6307
6308/* ------------------------------ */
6309    .balign 64
6310.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6311/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6312/* File: arm-vfp/fbinopWide2addr.S */
6313    /*
6314     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6315     * an "instr" line that specifies an instruction that performs
6316     * "d2 = d0 op d1".
6317     *
6318     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6319     *      div-double/2addr
6320     */
6321    /* binop/2addr vA, vB */
6322    mov     r3, rINST, lsr #12          @ r3<- B
6323    mov     r9, rINST, lsr #8           @ r9<- A+
6324    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6325    and     r9, r9, #15                 @ r9<- A
6326    fldd    d1, [r3]                    @ d1<- vB
6327    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6328    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6329    fldd    d0, [r9]                    @ d0<- vA
6330
6331    faddd   d2, d0, d1                              @ d2<- op
6332    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6333    fstd    d2, [r9]                    @ vAA<- d2
6334    GOTO_OPCODE(ip)                     @ jump to next instruction
6335
6336
6337/* ------------------------------ */
6338    .balign 64
6339.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6340/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6341/* File: arm-vfp/fbinopWide2addr.S */
6342    /*
6343     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6344     * an "instr" line that specifies an instruction that performs
6345     * "d2 = d0 op d1".
6346     *
6347     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6348     *      div-double/2addr
6349     */
6350    /* binop/2addr vA, vB */
6351    mov     r3, rINST, lsr #12          @ r3<- B
6352    mov     r9, rINST, lsr #8           @ r9<- A+
6353    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6354    and     r9, r9, #15                 @ r9<- A
6355    fldd    d1, [r3]                    @ d1<- vB
6356    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6357    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6358    fldd    d0, [r9]                    @ d0<- vA
6359
6360    fsubd   d2, d0, d1                              @ d2<- op
6361    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6362    fstd    d2, [r9]                    @ vAA<- d2
6363    GOTO_OPCODE(ip)                     @ jump to next instruction
6364
6365
6366/* ------------------------------ */
6367    .balign 64
6368.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6369/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6370/* File: arm-vfp/fbinopWide2addr.S */
6371    /*
6372     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6373     * an "instr" line that specifies an instruction that performs
6374     * "d2 = d0 op d1".
6375     *
6376     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6377     *      div-double/2addr
6378     */
6379    /* binop/2addr vA, vB */
6380    mov     r3, rINST, lsr #12          @ r3<- B
6381    mov     r9, rINST, lsr #8           @ r9<- A+
6382    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6383    and     r9, r9, #15                 @ r9<- A
6384    fldd    d1, [r3]                    @ d1<- vB
6385    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6386    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6387    fldd    d0, [r9]                    @ d0<- vA
6388
6389    fmuld   d2, d0, d1                              @ d2<- op
6390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6391    fstd    d2, [r9]                    @ vAA<- d2
6392    GOTO_OPCODE(ip)                     @ jump to next instruction
6393
6394
6395/* ------------------------------ */
6396    .balign 64
6397.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6398/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6399/* File: arm-vfp/fbinopWide2addr.S */
6400    /*
6401     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6402     * an "instr" line that specifies an instruction that performs
6403     * "d2 = d0 op d1".
6404     *
6405     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6406     *      div-double/2addr
6407     */
6408    /* binop/2addr vA, vB */
6409    mov     r3, rINST, lsr #12          @ r3<- B
6410    mov     r9, rINST, lsr #8           @ r9<- A+
6411    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6412    and     r9, r9, #15                 @ r9<- A
6413    fldd    d1, [r3]                    @ d1<- vB
6414    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6415    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6416    fldd    d0, [r9]                    @ d0<- vA
6417
6418    fdivd   d2, d0, d1                              @ d2<- op
6419    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6420    fstd    d2, [r9]                    @ vAA<- d2
6421    GOTO_OPCODE(ip)                     @ jump to next instruction
6422
6423
6424/* ------------------------------ */
6425    .balign 64
6426.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6427/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6428/* EABI doesn't define a double remainder function, but libm does */
6429/* File: armv5te/binopWide2addr.S */
6430    /*
6431     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6432     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6433     * This could be an ARM instruction or a function call.  (If the result
6434     * comes back in a register other than r0, you can override "result".)
6435     *
6436     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6437     * vCC (r1).  Useful for integer division and modulus.
6438     *
6439     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6440     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6441     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6442     *      rem-double/2addr
6443     */
6444    /* binop/2addr vA, vB */
6445    mov     r9, rINST, lsr #8           @ r9<- A+
6446    mov     r1, rINST, lsr #12          @ r1<- B
6447    and     r9, r9, #15
6448    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6449    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6450    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6451    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6452    .if 0
6453    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6454    beq     common_errDivideByZero
6455    .endif
6456    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6457
6458                               @ optional op; may set condition codes
6459    bl      fmod                              @ result<- op, r0-r3 changed
6460    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6461    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6462    GOTO_OPCODE(ip)                     @ jump to next instruction
6463    /* 12-15 instructions */
6464
6465
6466
6467/* ------------------------------ */
6468    .balign 64
6469.L_OP_ADD_INT_LIT16: /* 0xd0 */
6470/* File: armv5te/OP_ADD_INT_LIT16.S */
6471/* File: armv5te/binopLit16.S */
6472    /*
6473     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6474     * that specifies an instruction that performs "result = r0 op r1".
6475     * This could be an ARM instruction or a function call.  (If the result
6476     * comes back in a register other than r0, you can override "result".)
6477     *
6478     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6479     * vCC (r1).  Useful for integer division and modulus.
6480     *
6481     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6482     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6483     */
6484    /* binop/lit16 vA, vB, #+CCCC */
6485    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6486    mov     r2, rINST, lsr #12          @ r2<- B
6487    mov     r9, rINST, lsr #8           @ r9<- A+
6488    GET_VREG(r0, r2)                    @ r0<- vB
6489    and     r9, r9, #15
6490    .if 0
6491    cmp     r1, #0                      @ is second operand zero?
6492    beq     common_errDivideByZero
6493    .endif
6494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6495
6496    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6497    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6498    SET_VREG(r0, r9)               @ vAA<- r0
6499    GOTO_OPCODE(ip)                     @ jump to next instruction
6500    /* 10-13 instructions */
6501
6502
6503
6504/* ------------------------------ */
6505    .balign 64
6506.L_OP_RSUB_INT: /* 0xd1 */
6507/* File: armv5te/OP_RSUB_INT.S */
6508/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6509/* File: armv5te/binopLit16.S */
6510    /*
6511     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6512     * that specifies an instruction that performs "result = r0 op r1".
6513     * This could be an ARM instruction or a function call.  (If the result
6514     * comes back in a register other than r0, you can override "result".)
6515     *
6516     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6517     * vCC (r1).  Useful for integer division and modulus.
6518     *
6519     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6520     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6521     */
6522    /* binop/lit16 vA, vB, #+CCCC */
6523    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6524    mov     r2, rINST, lsr #12          @ r2<- B
6525    mov     r9, rINST, lsr #8           @ r9<- A+
6526    GET_VREG(r0, r2)                    @ r0<- vB
6527    and     r9, r9, #15
6528    .if 0
6529    cmp     r1, #0                      @ is second operand zero?
6530    beq     common_errDivideByZero
6531    .endif
6532    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6533
6534    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6536    SET_VREG(r0, r9)               @ vAA<- r0
6537    GOTO_OPCODE(ip)                     @ jump to next instruction
6538    /* 10-13 instructions */
6539
6540
6541
6542/* ------------------------------ */
6543    .balign 64
6544.L_OP_MUL_INT_LIT16: /* 0xd2 */
6545/* File: armv5te/OP_MUL_INT_LIT16.S */
6546/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6547/* File: armv5te/binopLit16.S */
6548    /*
6549     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6550     * that specifies an instruction that performs "result = r0 op r1".
6551     * This could be an ARM instruction or a function call.  (If the result
6552     * comes back in a register other than r0, you can override "result".)
6553     *
6554     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6555     * vCC (r1).  Useful for integer division and modulus.
6556     *
6557     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6558     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6559     */
6560    /* binop/lit16 vA, vB, #+CCCC */
6561    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6562    mov     r2, rINST, lsr #12          @ r2<- B
6563    mov     r9, rINST, lsr #8           @ r9<- A+
6564    GET_VREG(r0, r2)                    @ r0<- vB
6565    and     r9, r9, #15
6566    .if 0
6567    cmp     r1, #0                      @ is second operand zero?
6568    beq     common_errDivideByZero
6569    .endif
6570    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6571
6572    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6574    SET_VREG(r0, r9)               @ vAA<- r0
6575    GOTO_OPCODE(ip)                     @ jump to next instruction
6576    /* 10-13 instructions */
6577
6578
6579
6580/* ------------------------------ */
6581    .balign 64
6582.L_OP_DIV_INT_LIT16: /* 0xd3 */
6583/* File: armv5te/OP_DIV_INT_LIT16.S */
6584/* File: armv5te/binopLit16.S */
6585    /*
6586     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6587     * that specifies an instruction that performs "result = r0 op r1".
6588     * This could be an ARM instruction or a function call.  (If the result
6589     * comes back in a register other than r0, you can override "result".)
6590     *
6591     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6592     * vCC (r1).  Useful for integer division and modulus.
6593     *
6594     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6595     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6596     */
6597    /* binop/lit16 vA, vB, #+CCCC */
6598    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6599    mov     r2, rINST, lsr #12          @ r2<- B
6600    mov     r9, rINST, lsr #8           @ r9<- A+
6601    GET_VREG(r0, r2)                    @ r0<- vB
6602    and     r9, r9, #15
6603    .if 1
6604    cmp     r1, #0                      @ is second operand zero?
6605    beq     common_errDivideByZero
6606    .endif
6607    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6608
6609    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6610    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6611    SET_VREG(r0, r9)               @ vAA<- r0
6612    GOTO_OPCODE(ip)                     @ jump to next instruction
6613    /* 10-13 instructions */
6614
6615
6616
6617/* ------------------------------ */
6618    .balign 64
6619.L_OP_REM_INT_LIT16: /* 0xd4 */
6620/* File: armv5te/OP_REM_INT_LIT16.S */
6621/* idivmod returns quotient in r0 and remainder in r1 */
6622/* File: armv5te/binopLit16.S */
6623    /*
6624     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6625     * that specifies an instruction that performs "result = r0 op r1".
6626     * This could be an ARM instruction or a function call.  (If the result
6627     * comes back in a register other than r0, you can override "result".)
6628     *
6629     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6630     * vCC (r1).  Useful for integer division and modulus.
6631     *
6632     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6633     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6634     */
6635    /* binop/lit16 vA, vB, #+CCCC */
6636    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6637    mov     r2, rINST, lsr #12          @ r2<- B
6638    mov     r9, rINST, lsr #8           @ r9<- A+
6639    GET_VREG(r0, r2)                    @ r0<- vB
6640    and     r9, r9, #15
6641    .if 1
6642    cmp     r1, #0                      @ is second operand zero?
6643    beq     common_errDivideByZero
6644    .endif
6645    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6646
6647    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6648    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6649    SET_VREG(r1, r9)               @ vAA<- r1
6650    GOTO_OPCODE(ip)                     @ jump to next instruction
6651    /* 10-13 instructions */
6652
6653
6654
6655/* ------------------------------ */
6656    .balign 64
6657.L_OP_AND_INT_LIT16: /* 0xd5 */
6658/* File: armv5te/OP_AND_INT_LIT16.S */
6659/* File: armv5te/binopLit16.S */
6660    /*
6661     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6662     * that specifies an instruction that performs "result = r0 op r1".
6663     * This could be an ARM instruction or a function call.  (If the result
6664     * comes back in a register other than r0, you can override "result".)
6665     *
6666     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6667     * vCC (r1).  Useful for integer division and modulus.
6668     *
6669     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6670     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6671     */
6672    /* binop/lit16 vA, vB, #+CCCC */
6673    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6674    mov     r2, rINST, lsr #12          @ r2<- B
6675    mov     r9, rINST, lsr #8           @ r9<- A+
6676    GET_VREG(r0, r2)                    @ r0<- vB
6677    and     r9, r9, #15
6678    .if 0
6679    cmp     r1, #0                      @ is second operand zero?
6680    beq     common_errDivideByZero
6681    .endif
6682    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6683
6684    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6685    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6686    SET_VREG(r0, r9)               @ vAA<- r0
6687    GOTO_OPCODE(ip)                     @ jump to next instruction
6688    /* 10-13 instructions */
6689
6690
6691
6692/* ------------------------------ */
6693    .balign 64
6694.L_OP_OR_INT_LIT16: /* 0xd6 */
6695/* File: armv5te/OP_OR_INT_LIT16.S */
6696/* File: armv5te/binopLit16.S */
6697    /*
6698     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6699     * that specifies an instruction that performs "result = r0 op r1".
6700     * This could be an ARM instruction or a function call.  (If the result
6701     * comes back in a register other than r0, you can override "result".)
6702     *
6703     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6704     * vCC (r1).  Useful for integer division and modulus.
6705     *
6706     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6707     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6708     */
6709    /* binop/lit16 vA, vB, #+CCCC */
6710    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6711    mov     r2, rINST, lsr #12          @ r2<- B
6712    mov     r9, rINST, lsr #8           @ r9<- A+
6713    GET_VREG(r0, r2)                    @ r0<- vB
6714    and     r9, r9, #15
6715    .if 0
6716    cmp     r1, #0                      @ is second operand zero?
6717    beq     common_errDivideByZero
6718    .endif
6719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6720
6721    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6722    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6723    SET_VREG(r0, r9)               @ vAA<- r0
6724    GOTO_OPCODE(ip)                     @ jump to next instruction
6725    /* 10-13 instructions */
6726
6727
6728
6729/* ------------------------------ */
6730    .balign 64
6731.L_OP_XOR_INT_LIT16: /* 0xd7 */
6732/* File: armv5te/OP_XOR_INT_LIT16.S */
6733/* File: armv5te/binopLit16.S */
6734    /*
6735     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6736     * that specifies an instruction that performs "result = r0 op r1".
6737     * This could be an ARM instruction or a function call.  (If the result
6738     * comes back in a register other than r0, you can override "result".)
6739     *
6740     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6741     * vCC (r1).  Useful for integer division and modulus.
6742     *
6743     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6744     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6745     */
6746    /* binop/lit16 vA, vB, #+CCCC */
6747    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6748    mov     r2, rINST, lsr #12          @ r2<- B
6749    mov     r9, rINST, lsr #8           @ r9<- A+
6750    GET_VREG(r0, r2)                    @ r0<- vB
6751    and     r9, r9, #15
6752    .if 0
6753    cmp     r1, #0                      @ is second operand zero?
6754    beq     common_errDivideByZero
6755    .endif
6756    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6757
6758    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6760    SET_VREG(r0, r9)               @ vAA<- r0
6761    GOTO_OPCODE(ip)                     @ jump to next instruction
6762    /* 10-13 instructions */
6763
6764
6765
6766/* ------------------------------ */
6767    .balign 64
6768.L_OP_ADD_INT_LIT8: /* 0xd8 */
6769/* File: armv5te/OP_ADD_INT_LIT8.S */
6770/* File: armv5te/binopLit8.S */
6771    /*
6772     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6773     * that specifies an instruction that performs "result = r0 op r1".
6774     * This could be an ARM instruction or a function call.  (If the result
6775     * comes back in a register other than r0, you can override "result".)
6776     *
6777     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6778     * vCC (r1).  Useful for integer division and modulus.
6779     *
6780     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6781     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6782     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6783     */
6784    /* binop/lit8 vAA, vBB, #+CC */
6785    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6786    mov     r9, rINST, lsr #8           @ r9<- AA
6787    and     r2, r3, #255                @ r2<- BB
6788    GET_VREG(r0, r2)                    @ r0<- vBB
6789    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6790    .if 0
6791    @cmp     r1, #0                      @ is second operand zero?
6792    beq     common_errDivideByZero
6793    .endif
6794    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6795
6796                               @ optional op; may set condition codes
6797    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6799    SET_VREG(r0, r9)               @ vAA<- r0
6800    GOTO_OPCODE(ip)                     @ jump to next instruction
6801    /* 10-12 instructions */
6802
6803
6804
6805/* ------------------------------ */
6806    .balign 64
6807.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6808/* File: armv5te/OP_RSUB_INT_LIT8.S */
6809/* File: armv5te/binopLit8.S */
6810    /*
6811     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6812     * that specifies an instruction that performs "result = r0 op r1".
6813     * This could be an ARM instruction or a function call.  (If the result
6814     * comes back in a register other than r0, you can override "result".)
6815     *
6816     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6817     * vCC (r1).  Useful for integer division and modulus.
6818     *
6819     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6820     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6821     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6822     */
6823    /* binop/lit8 vAA, vBB, #+CC */
6824    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6825    mov     r9, rINST, lsr #8           @ r9<- AA
6826    and     r2, r3, #255                @ r2<- BB
6827    GET_VREG(r0, r2)                    @ r0<- vBB
6828    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6829    .if 0
6830    @cmp     r1, #0                      @ is second operand zero?
6831    beq     common_errDivideByZero
6832    .endif
6833    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6834
6835                               @ optional op; may set condition codes
6836    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6837    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6838    SET_VREG(r0, r9)               @ vAA<- r0
6839    GOTO_OPCODE(ip)                     @ jump to next instruction
6840    /* 10-12 instructions */
6841
6842
6843
6844/* ------------------------------ */
6845    .balign 64
6846.L_OP_MUL_INT_LIT8: /* 0xda */
6847/* File: armv5te/OP_MUL_INT_LIT8.S */
6848/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6849/* File: armv5te/binopLit8.S */
6850    /*
6851     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6852     * that specifies an instruction that performs "result = r0 op r1".
6853     * This could be an ARM instruction or a function call.  (If the result
6854     * comes back in a register other than r0, you can override "result".)
6855     *
6856     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6857     * vCC (r1).  Useful for integer division and modulus.
6858     *
6859     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6860     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6861     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6862     */
6863    /* binop/lit8 vAA, vBB, #+CC */
6864    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6865    mov     r9, rINST, lsr #8           @ r9<- AA
6866    and     r2, r3, #255                @ r2<- BB
6867    GET_VREG(r0, r2)                    @ r0<- vBB
6868    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6869    .if 0
6870    @cmp     r1, #0                      @ is second operand zero?
6871    beq     common_errDivideByZero
6872    .endif
6873    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6874
6875                               @ optional op; may set condition codes
6876    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6878    SET_VREG(r0, r9)               @ vAA<- r0
6879    GOTO_OPCODE(ip)                     @ jump to next instruction
6880    /* 10-12 instructions */
6881
6882
6883
6884/* ------------------------------ */
6885    .balign 64
6886.L_OP_DIV_INT_LIT8: /* 0xdb */
6887/* File: armv5te/OP_DIV_INT_LIT8.S */
6888/* File: armv5te/binopLit8.S */
6889    /*
6890     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6891     * that specifies an instruction that performs "result = r0 op r1".
6892     * This could be an ARM instruction or a function call.  (If the result
6893     * comes back in a register other than r0, you can override "result".)
6894     *
6895     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6896     * vCC (r1).  Useful for integer division and modulus.
6897     *
6898     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6899     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6900     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6901     */
6902    /* binop/lit8 vAA, vBB, #+CC */
6903    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6904    mov     r9, rINST, lsr #8           @ r9<- AA
6905    and     r2, r3, #255                @ r2<- BB
6906    GET_VREG(r0, r2)                    @ r0<- vBB
6907    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6908    .if 1
6909    @cmp     r1, #0                      @ is second operand zero?
6910    beq     common_errDivideByZero
6911    .endif
6912    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6913
6914                               @ optional op; may set condition codes
6915    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6916    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6917    SET_VREG(r0, r9)               @ vAA<- r0
6918    GOTO_OPCODE(ip)                     @ jump to next instruction
6919    /* 10-12 instructions */
6920
6921
6922
6923/* ------------------------------ */
6924    .balign 64
6925.L_OP_REM_INT_LIT8: /* 0xdc */
6926/* File: armv5te/OP_REM_INT_LIT8.S */
6927/* idivmod returns quotient in r0 and remainder in r1 */
6928/* File: armv5te/binopLit8.S */
6929    /*
6930     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6931     * that specifies an instruction that performs "result = r0 op r1".
6932     * This could be an ARM instruction or a function call.  (If the result
6933     * comes back in a register other than r0, you can override "result".)
6934     *
6935     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6936     * vCC (r1).  Useful for integer division and modulus.
6937     *
6938     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6939     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6940     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6941     */
6942    /* binop/lit8 vAA, vBB, #+CC */
6943    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6944    mov     r9, rINST, lsr #8           @ r9<- AA
6945    and     r2, r3, #255                @ r2<- BB
6946    GET_VREG(r0, r2)                    @ r0<- vBB
6947    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6948    .if 1
6949    @cmp     r1, #0                      @ is second operand zero?
6950    beq     common_errDivideByZero
6951    .endif
6952    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6953
6954                               @ optional op; may set condition codes
6955    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6956    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6957    SET_VREG(r1, r9)               @ vAA<- r1
6958    GOTO_OPCODE(ip)                     @ jump to next instruction
6959    /* 10-12 instructions */
6960
6961
6962
6963/* ------------------------------ */
6964    .balign 64
6965.L_OP_AND_INT_LIT8: /* 0xdd */
6966/* File: armv5te/OP_AND_INT_LIT8.S */
6967/* File: armv5te/binopLit8.S */
6968    /*
6969     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6970     * that specifies an instruction that performs "result = r0 op r1".
6971     * This could be an ARM instruction or a function call.  (If the result
6972     * comes back in a register other than r0, you can override "result".)
6973     *
6974     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6975     * vCC (r1).  Useful for integer division and modulus.
6976     *
6977     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6978     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6979     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6980     */
6981    /* binop/lit8 vAA, vBB, #+CC */
6982    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6983    mov     r9, rINST, lsr #8           @ r9<- AA
6984    and     r2, r3, #255                @ r2<- BB
6985    GET_VREG(r0, r2)                    @ r0<- vBB
6986    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6987    .if 0
6988    @cmp     r1, #0                      @ is second operand zero?
6989    beq     common_errDivideByZero
6990    .endif
6991    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6992
6993                               @ optional op; may set condition codes
6994    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6995    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6996    SET_VREG(r0, r9)               @ vAA<- r0
6997    GOTO_OPCODE(ip)                     @ jump to next instruction
6998    /* 10-12 instructions */
6999
7000
7001
7002/* ------------------------------ */
7003    .balign 64
7004.L_OP_OR_INT_LIT8: /* 0xde */
7005/* File: armv5te/OP_OR_INT_LIT8.S */
7006/* File: armv5te/binopLit8.S */
7007    /*
7008     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7009     * that specifies an instruction that performs "result = r0 op r1".
7010     * This could be an ARM instruction or a function call.  (If the result
7011     * comes back in a register other than r0, you can override "result".)
7012     *
7013     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7014     * vCC (r1).  Useful for integer division and modulus.
7015     *
7016     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7017     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7018     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7019     */
7020    /* binop/lit8 vAA, vBB, #+CC */
7021    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7022    mov     r9, rINST, lsr #8           @ r9<- AA
7023    and     r2, r3, #255                @ r2<- BB
7024    GET_VREG(r0, r2)                    @ r0<- vBB
7025    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7026    .if 0
7027    @cmp     r1, #0                      @ is second operand zero?
7028    beq     common_errDivideByZero
7029    .endif
7030    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7031
7032                               @ optional op; may set condition codes
7033    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7034    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7035    SET_VREG(r0, r9)               @ vAA<- r0
7036    GOTO_OPCODE(ip)                     @ jump to next instruction
7037    /* 10-12 instructions */
7038
7039
7040
7041/* ------------------------------ */
7042    .balign 64
7043.L_OP_XOR_INT_LIT8: /* 0xdf */
7044/* File: armv5te/OP_XOR_INT_LIT8.S */
7045/* File: armv5te/binopLit8.S */
7046    /*
7047     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7048     * that specifies an instruction that performs "result = r0 op r1".
7049     * This could be an ARM instruction or a function call.  (If the result
7050     * comes back in a register other than r0, you can override "result".)
7051     *
7052     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7053     * vCC (r1).  Useful for integer division and modulus.
7054     *
7055     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7056     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7057     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7058     */
7059    /* binop/lit8 vAA, vBB, #+CC */
7060    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7061    mov     r9, rINST, lsr #8           @ r9<- AA
7062    and     r2, r3, #255                @ r2<- BB
7063    GET_VREG(r0, r2)                    @ r0<- vBB
7064    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7065    .if 0
7066    @cmp     r1, #0                      @ is second operand zero?
7067    beq     common_errDivideByZero
7068    .endif
7069    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7070
7071                               @ optional op; may set condition codes
7072    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7074    SET_VREG(r0, r9)               @ vAA<- r0
7075    GOTO_OPCODE(ip)                     @ jump to next instruction
7076    /* 10-12 instructions */
7077
7078
7079
7080/* ------------------------------ */
7081    .balign 64
7082.L_OP_SHL_INT_LIT8: /* 0xe0 */
7083/* File: armv5te/OP_SHL_INT_LIT8.S */
7084/* File: armv5te/binopLit8.S */
7085    /*
7086     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7087     * that specifies an instruction that performs "result = r0 op r1".
7088     * This could be an ARM instruction or a function call.  (If the result
7089     * comes back in a register other than r0, you can override "result".)
7090     *
7091     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7092     * vCC (r1).  Useful for integer division and modulus.
7093     *
7094     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7095     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7096     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7097     */
7098    /* binop/lit8 vAA, vBB, #+CC */
7099    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7100    mov     r9, rINST, lsr #8           @ r9<- AA
7101    and     r2, r3, #255                @ r2<- BB
7102    GET_VREG(r0, r2)                    @ r0<- vBB
7103    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7104    .if 0
7105    @cmp     r1, #0                      @ is second operand zero?
7106    beq     common_errDivideByZero
7107    .endif
7108    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7109
7110    and     r1, r1, #31                           @ optional op; may set condition codes
7111    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7113    SET_VREG(r0, r9)               @ vAA<- r0
7114    GOTO_OPCODE(ip)                     @ jump to next instruction
7115    /* 10-12 instructions */
7116
7117
7118
7119/* ------------------------------ */
7120    .balign 64
7121.L_OP_SHR_INT_LIT8: /* 0xe1 */
7122/* File: armv5te/OP_SHR_INT_LIT8.S */
7123/* File: armv5te/binopLit8.S */
7124    /*
7125     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7126     * that specifies an instruction that performs "result = r0 op r1".
7127     * This could be an ARM instruction or a function call.  (If the result
7128     * comes back in a register other than r0, you can override "result".)
7129     *
7130     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7131     * vCC (r1).  Useful for integer division and modulus.
7132     *
7133     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7134     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7135     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7136     */
7137    /* binop/lit8 vAA, vBB, #+CC */
7138    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7139    mov     r9, rINST, lsr #8           @ r9<- AA
7140    and     r2, r3, #255                @ r2<- BB
7141    GET_VREG(r0, r2)                    @ r0<- vBB
7142    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7143    .if 0
7144    @cmp     r1, #0                      @ is second operand zero?
7145    beq     common_errDivideByZero
7146    .endif
7147    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7148
7149    and     r1, r1, #31                           @ optional op; may set condition codes
7150    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7152    SET_VREG(r0, r9)               @ vAA<- r0
7153    GOTO_OPCODE(ip)                     @ jump to next instruction
7154    /* 10-12 instructions */
7155
7156
7157
7158/* ------------------------------ */
7159    .balign 64
7160.L_OP_USHR_INT_LIT8: /* 0xe2 */
7161/* File: armv5te/OP_USHR_INT_LIT8.S */
7162/* File: armv5te/binopLit8.S */
7163    /*
7164     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7165     * that specifies an instruction that performs "result = r0 op r1".
7166     * This could be an ARM instruction or a function call.  (If the result
7167     * comes back in a register other than r0, you can override "result".)
7168     *
7169     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7170     * vCC (r1).  Useful for integer division and modulus.
7171     *
7172     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7173     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7174     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7175     */
7176    /* binop/lit8 vAA, vBB, #+CC */
7177    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7178    mov     r9, rINST, lsr #8           @ r9<- AA
7179    and     r2, r3, #255                @ r2<- BB
7180    GET_VREG(r0, r2)                    @ r0<- vBB
7181    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7182    .if 0
7183    @cmp     r1, #0                      @ is second operand zero?
7184    beq     common_errDivideByZero
7185    .endif
7186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7187
7188    and     r1, r1, #31                           @ optional op; may set condition codes
7189    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7191    SET_VREG(r0, r9)               @ vAA<- r0
7192    GOTO_OPCODE(ip)                     @ jump to next instruction
7193    /* 10-12 instructions */
7194
7195
7196
7197/* ------------------------------ */
7198    .balign 64
7199.L_OP_UNUSED_E3: /* 0xe3 */
7200/* File: armv5te/OP_UNUSED_E3.S */
7201/* File: armv5te/unused.S */
7202    bl      common_abort
7203
7204
7205
7206/* ------------------------------ */
7207    .balign 64
7208.L_OP_UNUSED_E4: /* 0xe4 */
7209/* File: armv5te/OP_UNUSED_E4.S */
7210/* File: armv5te/unused.S */
7211    bl      common_abort
7212
7213
7214
7215/* ------------------------------ */
7216    .balign 64
7217.L_OP_UNUSED_E5: /* 0xe5 */
7218/* File: armv5te/OP_UNUSED_E5.S */
7219/* File: armv5te/unused.S */
7220    bl      common_abort
7221
7222
7223
7224/* ------------------------------ */
7225    .balign 64
7226.L_OP_UNUSED_E6: /* 0xe6 */
7227/* File: armv5te/OP_UNUSED_E6.S */
7228/* File: armv5te/unused.S */
7229    bl      common_abort
7230
7231
7232
7233/* ------------------------------ */
7234    .balign 64
7235.L_OP_UNUSED_E7: /* 0xe7 */
7236/* File: armv5te/OP_UNUSED_E7.S */
7237/* File: armv5te/unused.S */
7238    bl      common_abort
7239
7240
7241
7242/* ------------------------------ */
7243    .balign 64
7244.L_OP_UNUSED_E8: /* 0xe8 */
7245/* File: armv5te/OP_UNUSED_E8.S */
7246/* File: armv5te/unused.S */
7247    bl      common_abort
7248
7249
7250
7251/* ------------------------------ */
7252    .balign 64
7253.L_OP_UNUSED_E9: /* 0xe9 */
7254/* File: armv5te/OP_UNUSED_E9.S */
7255/* File: armv5te/unused.S */
7256    bl      common_abort
7257
7258
7259
7260/* ------------------------------ */
7261    .balign 64
7262.L_OP_UNUSED_EA: /* 0xea */
7263/* File: armv5te/OP_UNUSED_EA.S */
7264/* File: armv5te/unused.S */
7265    bl      common_abort
7266
7267
7268
7269/* ------------------------------ */
7270    .balign 64
7271.L_OP_UNUSED_EB: /* 0xeb */
7272/* File: armv5te/OP_UNUSED_EB.S */
7273/* File: armv5te/unused.S */
7274    bl      common_abort
7275
7276
7277
7278/* ------------------------------ */
7279    .balign 64
7280.L_OP_BREAKPOINT: /* 0xec */
7281/* File: armv5te/OP_BREAKPOINT.S */
7282/* File: armv5te/unused.S */
7283    bl      common_abort
7284
7285
7286
7287/* ------------------------------ */
7288    .balign 64
7289.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7290/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7291    /*
7292     * Handle a throw-verification-error instruction.  This throws an
7293     * exception for an error discovered during verification.  The
7294     * exception is indicated by AA, with some detail provided by BBBB.
7295     */
7296    /* op AA, ref@BBBB */
7297    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7298    FETCH(r2, 1)                        @ r2<- BBBB
7299    EXPORT_PC()                         @ export the PC
7300    mov     r1, rINST, lsr #8           @ r1<- AA
7301    bl      dvmThrowVerificationError   @ always throws
7302    b       common_exceptionThrown      @ handle exception
7303
7304
7305/* ------------------------------ */
7306    .balign 64
7307.L_OP_EXECUTE_INLINE: /* 0xee */
7308/* File: armv5te/OP_EXECUTE_INLINE.S */
7309    /*
7310     * Execute a "native inline" instruction.
7311     *
7312     * We need to call an InlineOp4Func:
7313     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7314     *
7315     * The first four args are in r0-r3, pointer to return value storage
7316     * is on the stack.  The function's return value is a flag that tells
7317     * us if an exception was thrown.
7318     */
7319    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7320    FETCH(r10, 1)                       @ r10<- BBBB
7321    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7322    EXPORT_PC()                         @ can throw
7323    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7324    mov     r0, rINST, lsr #12          @ r0<- B
7325    str     r1, [sp]                    @ push &glue->retval
7326    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7327    add     sp, sp, #8                  @ pop stack
7328    cmp     r0, #0                      @ test boolean result of inline
7329    beq     common_exceptionThrown      @ returned false, handle exception
7330    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7331    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7332    GOTO_OPCODE(ip)                     @ jump to next instruction
7333
7334/* ------------------------------ */
7335    .balign 64
7336.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7337/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7338    /*
7339     * Execute a "native inline" instruction, using "/range" semantics.
7340     * Same idea as execute-inline, but we get the args differently.
7341     *
7342     * We need to call an InlineOp4Func:
7343     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7344     *
7345     * The first four args are in r0-r3, pointer to return value storage
7346     * is on the stack.  The function's return value is a flag that tells
7347     * us if an exception was thrown.
7348     */
7349    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7350    FETCH(r10, 1)                       @ r10<- BBBB
7351    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7352    EXPORT_PC()                         @ can throw
7353    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7354    mov     r0, rINST, lsr #8           @ r0<- AA
7355    str     r1, [sp]                    @ push &glue->retval
7356    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7357    add     sp, sp, #8                  @ pop stack
7358    cmp     r0, #0                      @ test boolean result of inline
7359    beq     common_exceptionThrown      @ returned false, handle exception
7360    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7361    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7362    GOTO_OPCODE(ip)                     @ jump to next instruction
7363
7364/* ------------------------------ */
7365    .balign 64
7366.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7367/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7368    /*
7369     * invoke-direct-empty is a no-op in a "standard" interpreter.
7370     */
7371    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7372    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7373    GOTO_OPCODE(ip)                     @ execute it
7374
7375/* ------------------------------ */
7376    .balign 64
7377.L_OP_UNUSED_F1: /* 0xf1 */
7378/* File: armv5te/OP_UNUSED_F1.S */
7379/* File: armv5te/unused.S */
7380    bl      common_abort
7381
7382
7383
7384/* ------------------------------ */
7385    .balign 64
7386.L_OP_IGET_QUICK: /* 0xf2 */
7387/* File: armv5te/OP_IGET_QUICK.S */
7388    /* For: iget-quick, iget-object-quick */
7389    /* op vA, vB, offset@CCCC */
7390    mov     r2, rINST, lsr #12          @ r2<- B
7391    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7392    FETCH(r1, 1)                        @ r1<- field byte offset
7393    cmp     r3, #0                      @ check object for null
7394    mov     r2, rINST, lsr #8           @ r2<- A(+)
7395    beq     common_errNullObject        @ object was null
7396    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7397    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7398    and     r2, r2, #15
7399    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7400    SET_VREG(r0, r2)                    @ fp[A]<- r0
7401    GOTO_OPCODE(ip)                     @ jump to next instruction
7402
7403
7404/* ------------------------------ */
7405    .balign 64
7406.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7407/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7408    /* iget-wide-quick vA, vB, offset@CCCC */
7409    mov     r2, rINST, lsr #12          @ r2<- B
7410    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7411    FETCH(r1, 1)                        @ r1<- field byte offset
7412    cmp     r3, #0                      @ check object for null
7413    mov     r2, rINST, lsr #8           @ r2<- A(+)
7414    beq     common_errNullObject        @ object was null
7415    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7416    and     r2, r2, #15
7417    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7418    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7419    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7420    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7421    GOTO_OPCODE(ip)                     @ jump to next instruction
7422
7423
7424/* ------------------------------ */
7425    .balign 64
7426.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7427/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7428/* File: armv5te/OP_IGET_QUICK.S */
7429    /* For: iget-quick, iget-object-quick */
7430    /* op vA, vB, offset@CCCC */
7431    mov     r2, rINST, lsr #12          @ r2<- B
7432    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7433    FETCH(r1, 1)                        @ r1<- field byte offset
7434    cmp     r3, #0                      @ check object for null
7435    mov     r2, rINST, lsr #8           @ r2<- A(+)
7436    beq     common_errNullObject        @ object was null
7437    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7438    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7439    and     r2, r2, #15
7440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7441    SET_VREG(r0, r2)                    @ fp[A]<- r0
7442    GOTO_OPCODE(ip)                     @ jump to next instruction
7443
7444
7445
7446/* ------------------------------ */
7447    .balign 64
7448.L_OP_IPUT_QUICK: /* 0xf5 */
7449/* File: armv5te/OP_IPUT_QUICK.S */
7450    /* For: iput-quick, iput-object-quick */
7451    /* op vA, vB, offset@CCCC */
7452    mov     r2, rINST, lsr #12          @ r2<- B
7453    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7454    FETCH(r1, 1)                        @ r1<- field byte offset
7455    cmp     r3, #0                      @ check object for null
7456    mov     r2, rINST, lsr #8           @ r2<- A(+)
7457    beq     common_errNullObject        @ object was null
7458    and     r2, r2, #15
7459    GET_VREG(r0, r2)                    @ r0<- fp[A]
7460    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7461    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7462    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7463    GOTO_OPCODE(ip)                     @ jump to next instruction
7464
7465
7466/* ------------------------------ */
7467    .balign 64
7468.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7469/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7470    /* iput-wide-quick vA, vB, offset@CCCC */
7471    mov     r0, rINST, lsr #8           @ r0<- A(+)
7472    mov     r1, rINST, lsr #12          @ r1<- B
7473    and     r0, r0, #15
7474    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7475    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7476    cmp     r2, #0                      @ check object for null
7477    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7478    beq     common_errNullObject        @ object was null
7479    FETCH(r3, 1)                        @ r3<- field byte offset
7480    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7481    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7482    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7483    GOTO_OPCODE(ip)                     @ jump to next instruction
7484
7485
7486/* ------------------------------ */
7487    .balign 64
7488.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7489/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7490/* File: armv5te/OP_IPUT_QUICK.S */
7491    /* For: iput-quick, iput-object-quick */
7492    /* op vA, vB, offset@CCCC */
7493    mov     r2, rINST, lsr #12          @ r2<- B
7494    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7495    FETCH(r1, 1)                        @ r1<- field byte offset
7496    cmp     r3, #0                      @ check object for null
7497    mov     r2, rINST, lsr #8           @ r2<- A(+)
7498    beq     common_errNullObject        @ object was null
7499    and     r2, r2, #15
7500    GET_VREG(r0, r2)                    @ r0<- fp[A]
7501    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7502    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7504    GOTO_OPCODE(ip)                     @ jump to next instruction
7505
7506
7507
7508/* ------------------------------ */
7509    .balign 64
7510.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7511/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7512    /*
7513     * Handle an optimized virtual method call.
7514     *
7515     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7516     */
7517    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7518    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7519    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7520    FETCH(r1, 1)                        @ r1<- BBBB
7521    .if     (!0)
7522    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7523    .endif
7524    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7525    cmp     r2, #0                      @ is "this" null?
7526    beq     common_errNullObject        @ null "this", throw exception
7527    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7528    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7529    EXPORT_PC()                         @ invoke must export
7530    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7531    bl      common_invokeMethodNoRange @ continue on
7532
7533/* ------------------------------ */
7534    .balign 64
7535.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7536/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7537/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7538    /*
7539     * Handle an optimized virtual method call.
7540     *
7541     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7542     */
7543    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7544    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7545    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7546    FETCH(r1, 1)                        @ r1<- BBBB
7547    .if     (!1)
7548    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7549    .endif
7550    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7551    cmp     r2, #0                      @ is "this" null?
7552    beq     common_errNullObject        @ null "this", throw exception
7553    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7554    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7555    EXPORT_PC()                         @ invoke must export
7556    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7557    bl      common_invokeMethodRange @ continue on
7558
7559
7560/* ------------------------------ */
7561    .balign 64
7562.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7563/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7564    /*
7565     * Handle an optimized "super" method call.
7566     *
7567     * for: [opt] invoke-super-quick, invoke-super-quick/range
7568     */
7569    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7570    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7571    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7572    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7573    .if     (!0)
7574    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7575    .endif
7576    FETCH(r1, 1)                        @ r1<- BBBB
7577    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7578    EXPORT_PC()                         @ must export for invoke
7579    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7580    GET_VREG(r3, r10)                   @ r3<- "this"
7581    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7582    cmp     r3, #0                      @ null "this" ref?
7583    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7584    beq     common_errNullObject        @ "this" is null, throw exception
7585    bl      common_invokeMethodNoRange @ continue on
7586
7587
7588/* ------------------------------ */
7589    .balign 64
7590.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7591/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7592/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7593    /*
7594     * Handle an optimized "super" method call.
7595     *
7596     * for: [opt] invoke-super-quick, invoke-super-quick/range
7597     */
7598    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7599    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7600    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7601    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7602    .if     (!1)
7603    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7604    .endif
7605    FETCH(r1, 1)                        @ r1<- BBBB
7606    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7607    EXPORT_PC()                         @ must export for invoke
7608    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7609    GET_VREG(r3, r10)                   @ r3<- "this"
7610    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7611    cmp     r3, #0                      @ null "this" ref?
7612    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7613    beq     common_errNullObject        @ "this" is null, throw exception
7614    bl      common_invokeMethodRange @ continue on
7615
7616
7617
7618/* ------------------------------ */
7619    .balign 64
7620.L_OP_UNUSED_FC: /* 0xfc */
7621/* File: armv5te/OP_UNUSED_FC.S */
7622/* File: armv5te/unused.S */
7623    bl      common_abort
7624
7625
7626
7627/* ------------------------------ */
7628    .balign 64
7629.L_OP_UNUSED_FD: /* 0xfd */
7630/* File: armv5te/OP_UNUSED_FD.S */
7631/* File: armv5te/unused.S */
7632    bl      common_abort
7633
7634
7635
7636/* ------------------------------ */
7637    .balign 64
7638.L_OP_UNUSED_FE: /* 0xfe */
7639/* File: armv5te/OP_UNUSED_FE.S */
7640/* File: armv5te/unused.S */
7641    bl      common_abort
7642
7643
7644
7645/* ------------------------------ */
7646    .balign 64
7647.L_OP_UNUSED_FF: /* 0xff */
7648/* File: armv5te/OP_UNUSED_FF.S */
7649/* File: armv5te/unused.S */
7650    bl      common_abort
7651
7652
7653
7654
7655    .balign 64
7656    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7657    .global dvmAsmInstructionEnd
7658dvmAsmInstructionEnd:
7659
7660/*
7661 * ===========================================================================
7662 *  Sister implementations
7663 * ===========================================================================
7664 */
7665    .global dvmAsmSisterStart
7666    .type   dvmAsmSisterStart, %function
7667    .text
7668    .balign 4
7669dvmAsmSisterStart:
7670
7671/* continuation for OP_CONST_STRING */
7672
7673    /*
7674     * Continuation if the String has not yet been resolved.
7675     *  r1: BBBB (String ref)
7676     *  r9: target register
7677     */
7678.LOP_CONST_STRING_resolve:
7679    EXPORT_PC()
7680    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7681    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7682    bl      dvmResolveString            @ r0<- String reference
7683    cmp     r0, #0                      @ failed?
7684    beq     common_exceptionThrown      @ yup, handle the exception
7685    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7686    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7687    SET_VREG(r0, r9)                    @ vAA<- r0
7688    GOTO_OPCODE(ip)                     @ jump to next instruction
7689
7690
7691/* continuation for OP_CONST_STRING_JUMBO */
7692
7693    /*
7694     * Continuation if the String has not yet been resolved.
7695     *  r1: BBBBBBBB (String ref)
7696     *  r9: target register
7697     */
7698.LOP_CONST_STRING_JUMBO_resolve:
7699    EXPORT_PC()
7700    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7701    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7702    bl      dvmResolveString            @ r0<- String reference
7703    cmp     r0, #0                      @ failed?
7704    beq     common_exceptionThrown      @ yup, handle the exception
7705    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7706    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7707    SET_VREG(r0, r9)                    @ vAA<- r0
7708    GOTO_OPCODE(ip)                     @ jump to next instruction
7709
7710
7711/* continuation for OP_CONST_CLASS */
7712
7713    /*
7714     * Continuation if the Class has not yet been resolved.
7715     *  r1: BBBB (Class ref)
7716     *  r9: target register
7717     */
7718.LOP_CONST_CLASS_resolve:
7719    EXPORT_PC()
7720    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7721    mov     r2, #1                      @ r2<- true
7722    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7723    bl      dvmResolveClass             @ r0<- Class reference
7724    cmp     r0, #0                      @ failed?
7725    beq     common_exceptionThrown      @ yup, handle the exception
7726    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7728    SET_VREG(r0, r9)                    @ vAA<- r0
7729    GOTO_OPCODE(ip)                     @ jump to next instruction
7730
7731
7732/* continuation for OP_CHECK_CAST */
7733
7734    /*
7735     * Trivial test failed, need to perform full check.  This is common.
7736     *  r0 holds obj->clazz
7737     *  r1 holds class resolved from BBBB
7738     *  r9 holds object
7739     */
7740.LOP_CHECK_CAST_fullcheck:
7741    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7742    cmp     r0, #0                      @ failed?
7743    bne     .LOP_CHECK_CAST_okay            @ no, success
7744
7745    @ A cast has failed.  We need to throw a ClassCastException with the
7746    @ class of the object that failed to be cast.
7747    EXPORT_PC()                         @ about to throw
7748    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7749    ldr     r0, .LstrClassCastExceptionPtr
7750    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7751    bl      dvmThrowExceptionWithClassMessage
7752    b       common_exceptionThrown
7753
7754    /*
7755     * Resolution required.  This is the least-likely path.
7756     *
7757     *  r2 holds BBBB
7758     *  r9 holds object
7759     */
7760.LOP_CHECK_CAST_resolve:
7761    EXPORT_PC()                         @ resolve() could throw
7762    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7763    mov     r1, r2                      @ r1<- BBBB
7764    mov     r2, #0                      @ r2<- false
7765    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7766    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7767    cmp     r0, #0                      @ got null?
7768    beq     common_exceptionThrown      @ yes, handle exception
7769    mov     r1, r0                      @ r1<- class resolved from BBB
7770    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7771    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7772
7773.LstrClassCastExceptionPtr:
7774    .word   .LstrClassCastException
7775
7776
7777/* continuation for OP_INSTANCE_OF */
7778
7779    /*
7780     * Trivial test failed, need to perform full check.  This is common.
7781     *  r0 holds obj->clazz
7782     *  r1 holds class resolved from BBBB
7783     *  r9 holds A
7784     */
7785.LOP_INSTANCE_OF_fullcheck:
7786    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7787    @ fall through to OP_INSTANCE_OF_store
7788
7789    /*
7790     * r0 holds boolean result
7791     * r9 holds A
7792     */
7793.LOP_INSTANCE_OF_store:
7794    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7795    SET_VREG(r0, r9)                    @ vA<- r0
7796    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7797    GOTO_OPCODE(ip)                     @ jump to next instruction
7798
7799    /*
7800     * Trivial test succeeded, save and bail.
7801     *  r9 holds A
7802     */
7803.LOP_INSTANCE_OF_trivial:
7804    mov     r0, #1                      @ indicate success
7805    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7806    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7807    SET_VREG(r0, r9)                    @ vA<- r0
7808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7809    GOTO_OPCODE(ip)                     @ jump to next instruction
7810
7811    /*
7812     * Resolution required.  This is the least-likely path.
7813     *
7814     *  r3 holds BBBB
7815     *  r9 holds A
7816     */
7817.LOP_INSTANCE_OF_resolve:
7818    EXPORT_PC()                         @ resolve() could throw
7819    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7820    mov     r1, r3                      @ r1<- BBBB
7821    mov     r2, #1                      @ r2<- true
7822    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7823    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7824    cmp     r0, #0                      @ got null?
7825    beq     common_exceptionThrown      @ yes, handle exception
7826    mov     r1, r0                      @ r1<- class resolved from BBB
7827    mov     r3, rINST, lsr #12          @ r3<- B
7828    GET_VREG(r0, r3)                    @ r0<- vB (object)
7829    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7830    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7831
7832
7833/* continuation for OP_NEW_INSTANCE */
7834
7835    .balign 32                          @ minimize cache lines
7836.LOP_NEW_INSTANCE_finish: @ r0=new object
7837    mov     r3, rINST, lsr #8           @ r3<- AA
7838    cmp     r0, #0                      @ failed?
7839    beq     common_exceptionThrown      @ yes, handle the exception
7840    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7842    SET_VREG(r0, r3)                    @ vAA<- r0
7843    GOTO_OPCODE(ip)                     @ jump to next instruction
7844
7845    /*
7846     * Class initialization required.
7847     *
7848     *  r0 holds class object
7849     */
7850.LOP_NEW_INSTANCE_needinit:
7851    mov     r9, r0                      @ save r0
7852    bl      dvmInitClass                @ initialize class
7853    cmp     r0, #0                      @ check boolean result
7854    mov     r0, r9                      @ restore r0
7855    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7856    b       common_exceptionThrown      @ failed, deal with init exception
7857
7858    /*
7859     * Resolution required.  This is the least-likely path.
7860     *
7861     *  r1 holds BBBB
7862     */
7863.LOP_NEW_INSTANCE_resolve:
7864    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7865    mov     r2, #0                      @ r2<- false
7866    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7867    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7868    cmp     r0, #0                      @ got null?
7869    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7870    b       common_exceptionThrown      @ yes, handle exception
7871
7872.LstrInstantiationErrorPtr:
7873    .word   .LstrInstantiationError
7874
7875
7876/* continuation for OP_NEW_ARRAY */
7877
7878
7879    /*
7880     * Resolve class.  (This is an uncommon case.)
7881     *
7882     *  r1 holds array length
7883     *  r2 holds class ref CCCC
7884     */
7885.LOP_NEW_ARRAY_resolve:
7886    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7887    mov     r9, r1                      @ r9<- length (save)
7888    mov     r1, r2                      @ r1<- CCCC
7889    mov     r2, #0                      @ r2<- false
7890    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7891    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7892    cmp     r0, #0                      @ got null?
7893    mov     r1, r9                      @ r1<- length (restore)
7894    beq     common_exceptionThrown      @ yes, handle exception
7895    @ fall through to OP_NEW_ARRAY_finish
7896
7897    /*
7898     * Finish allocation.
7899     *
7900     *  r0 holds class
7901     *  r1 holds array length
7902     */
7903.LOP_NEW_ARRAY_finish:
7904    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7905    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7906    cmp     r0, #0                      @ failed?
7907    mov     r2, rINST, lsr #8           @ r2<- A+
7908    beq     common_exceptionThrown      @ yes, handle the exception
7909    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7910    and     r2, r2, #15                 @ r2<- A
7911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7912    SET_VREG(r0, r2)                    @ vA<- r0
7913    GOTO_OPCODE(ip)                     @ jump to next instruction
7914
7915
7916/* continuation for OP_FILLED_NEW_ARRAY */
7917
7918    /*
7919     * On entry:
7920     *  r0 holds array class
7921     *  r10 holds AA or BA
7922     */
7923.LOP_FILLED_NEW_ARRAY_continue:
7924    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7925    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7926    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7927    .if     0
7928    mov     r1, r10                     @ r1<- AA (length)
7929    .else
7930    mov     r1, r10, lsr #4             @ r1<- B (length)
7931    .endif
7932    cmp     r3, #'I'                    @ array of ints?
7933    cmpne   r3, #'L'                    @ array of objects?
7934    cmpne   r3, #'['                    @ array of arrays?
7935    mov     r9, r1                      @ save length in r9
7936    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7937    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7938    cmp     r0, #0                      @ null return?
7939    beq     common_exceptionThrown      @ alloc failed, handle exception
7940
7941    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7942    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7943    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7944    subs    r9, r9, #1                  @ length--, check for neg
7945    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7946    bmi     2f                          @ was zero, bail
7947
7948    @ copy values from registers into the array
7949    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7950    .if     0
7951    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79521:  ldr     r3, [r2], #4                @ r3<- *r2++
7953    subs    r9, r9, #1                  @ count--
7954    str     r3, [r0], #4                @ *contents++ = vX
7955    bpl     1b
7956    @ continue at 2
7957    .else
7958    cmp     r9, #4                      @ length was initially 5?
7959    and     r2, r10, #15                @ r2<- A
7960    bne     1f                          @ <= 4 args, branch
7961    GET_VREG(r3, r2)                    @ r3<- vA
7962    sub     r9, r9, #1                  @ count--
7963    str     r3, [r0, #16]               @ contents[4] = vA
79641:  and     r2, r1, #15                 @ r2<- F/E/D/C
7965    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7966    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7967    subs    r9, r9, #1                  @ count--
7968    str     r3, [r0], #4                @ *contents++ = vX
7969    bpl     1b
7970    @ continue at 2
7971    .endif
7972
79732:
7974    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7975    GOTO_OPCODE(ip)                     @ execute it
7976
7977    /*
7978     * Throw an exception indicating that we have not implemented this
7979     * mode of filled-new-array.
7980     */
7981.LOP_FILLED_NEW_ARRAY_notimpl:
7982    ldr     r0, .L_strInternalError
7983    ldr     r1, .L_strFilledNewArrayNotImpl
7984    bl      dvmThrowException
7985    b       common_exceptionThrown
7986
7987    .if     (!0)                 @ define in one or the other, not both
7988.L_strFilledNewArrayNotImpl:
7989    .word   .LstrFilledNewArrayNotImpl
7990.L_strInternalError:
7991    .word   .LstrInternalError
7992    .endif
7993
7994
7995/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7996
7997    /*
7998     * On entry:
7999     *  r0 holds array class
8000     *  r10 holds AA or BA
8001     */
8002.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8003    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8004    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8005    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8006    .if     1
8007    mov     r1, r10                     @ r1<- AA (length)
8008    .else
8009    mov     r1, r10, lsr #4             @ r1<- B (length)
8010    .endif
8011    cmp     r3, #'I'                    @ array of ints?
8012    cmpne   r3, #'L'                    @ array of objects?
8013    cmpne   r3, #'['                    @ array of arrays?
8014    mov     r9, r1                      @ save length in r9
8015    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8016    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8017    cmp     r0, #0                      @ null return?
8018    beq     common_exceptionThrown      @ alloc failed, handle exception
8019
8020    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8021    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8022    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8023    subs    r9, r9, #1                  @ length--, check for neg
8024    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8025    bmi     2f                          @ was zero, bail
8026
8027    @ copy values from registers into the array
8028    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8029    .if     1
8030    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80311:  ldr     r3, [r2], #4                @ r3<- *r2++
8032    subs    r9, r9, #1                  @ count--
8033    str     r3, [r0], #4                @ *contents++ = vX
8034    bpl     1b
8035    @ continue at 2
8036    .else
8037    cmp     r9, #4                      @ length was initially 5?
8038    and     r2, r10, #15                @ r2<- A
8039    bne     1f                          @ <= 4 args, branch
8040    GET_VREG(r3, r2)                    @ r3<- vA
8041    sub     r9, r9, #1                  @ count--
8042    str     r3, [r0, #16]               @ contents[4] = vA
80431:  and     r2, r1, #15                 @ r2<- F/E/D/C
8044    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8045    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8046    subs    r9, r9, #1                  @ count--
8047    str     r3, [r0], #4                @ *contents++ = vX
8048    bpl     1b
8049    @ continue at 2
8050    .endif
8051
80522:
8053    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8054    GOTO_OPCODE(ip)                     @ execute it
8055
8056    /*
8057     * Throw an exception indicating that we have not implemented this
8058     * mode of filled-new-array.
8059     */
8060.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8061    ldr     r0, .L_strInternalError
8062    ldr     r1, .L_strFilledNewArrayNotImpl
8063    bl      dvmThrowException
8064    b       common_exceptionThrown
8065
8066    .if     (!1)                 @ define in one or the other, not both
8067.L_strFilledNewArrayNotImpl:
8068    .word   .LstrFilledNewArrayNotImpl
8069.L_strInternalError:
8070    .word   .LstrInternalError
8071    .endif
8072
8073
8074/* continuation for OP_CMPL_FLOAT */
8075.LOP_CMPL_FLOAT_finish:
8076    SET_VREG(r0, r9)                    @ vAA<- r0
8077    GOTO_OPCODE(ip)                     @ jump to next instruction
8078
8079
8080/* continuation for OP_CMPG_FLOAT */
8081.LOP_CMPG_FLOAT_finish:
8082    SET_VREG(r0, r9)                    @ vAA<- r0
8083    GOTO_OPCODE(ip)                     @ jump to next instruction
8084
8085
8086/* continuation for OP_CMPL_DOUBLE */
8087.LOP_CMPL_DOUBLE_finish:
8088    SET_VREG(r0, r9)                    @ vAA<- r0
8089    GOTO_OPCODE(ip)                     @ jump to next instruction
8090
8091
8092/* continuation for OP_CMPG_DOUBLE */
8093.LOP_CMPG_DOUBLE_finish:
8094    SET_VREG(r0, r9)                    @ vAA<- r0
8095    GOTO_OPCODE(ip)                     @ jump to next instruction
8096
8097
8098/* continuation for OP_CMP_LONG */
8099
8100.LOP_CMP_LONG_less:
8101    mvn     r1, #0                      @ r1<- -1
8102    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8103    @ instead, we just replicate the tail end.
8104    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8105    SET_VREG(r1, r9)                    @ vAA<- r1
8106    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8107    GOTO_OPCODE(ip)                     @ jump to next instruction
8108
8109.LOP_CMP_LONG_greater:
8110    mov     r1, #1                      @ r1<- 1
8111    @ fall through to _finish
8112
8113.LOP_CMP_LONG_finish:
8114    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8115    SET_VREG(r1, r9)                    @ vAA<- r1
8116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8117    GOTO_OPCODE(ip)                     @ jump to next instruction
8118
8119
8120/* continuation for OP_AGET_WIDE */
8121
8122.LOP_AGET_WIDE_finish:
8123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8124    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8125    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8126    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8127    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8128    GOTO_OPCODE(ip)                     @ jump to next instruction
8129
8130
8131/* continuation for OP_APUT_WIDE */
8132
8133.LOP_APUT_WIDE_finish:
8134    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8135    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8136    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8137    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8138    GOTO_OPCODE(ip)                     @ jump to next instruction
8139
8140
8141/* continuation for OP_APUT_OBJECT */
8142    /*
8143     * On entry:
8144     *  r1 = vBB (arrayObj)
8145     *  r9 = vAA (obj)
8146     *  r10 = offset into array (vBB + vCC * width)
8147     */
8148.LOP_APUT_OBJECT_finish:
8149    cmp     r9, #0                      @ storing null reference?
8150    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8151    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8152    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8153    bl      dvmCanPutArrayElement       @ test object type vs. array type
8154    cmp     r0, #0                      @ okay?
8155    beq     common_errArrayStore        @ no
8156.LOP_APUT_OBJECT_skip_check:
8157    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8159    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8160    GOTO_OPCODE(ip)                     @ jump to next instruction
8161
8162
8163/* continuation for OP_IGET */
8164
8165    /*
8166     * Currently:
8167     *  r0 holds resolved field
8168     *  r9 holds object
8169     */
8170.LOP_IGET_finish:
8171    @bl      common_squeak0
8172    cmp     r9, #0                      @ check object for null
8173    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8174    beq     common_errNullObject        @ object was null
8175    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8176    mov     r2, rINST, lsr #8           @ r2<- A+
8177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8178    and     r2, r2, #15                 @ r2<- A
8179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8180    SET_VREG(r0, r2)                    @ fp[A]<- r0
8181    GOTO_OPCODE(ip)                     @ jump to next instruction
8182
8183
8184/* continuation for OP_IGET_WIDE */
8185
8186    /*
8187     * Currently:
8188     *  r0 holds resolved field
8189     *  r9 holds object
8190     */
8191.LOP_IGET_WIDE_finish:
8192    cmp     r9, #0                      @ check object for null
8193    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8194    beq     common_errNullObject        @ object was null
8195    mov     r2, rINST, lsr #8           @ r2<- A+
8196    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8197    and     r2, r2, #15                 @ r2<- A
8198    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8199    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8201    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8202    GOTO_OPCODE(ip)                     @ jump to next instruction
8203
8204
8205/* continuation for OP_IGET_OBJECT */
8206
8207    /*
8208     * Currently:
8209     *  r0 holds resolved field
8210     *  r9 holds object
8211     */
8212.LOP_IGET_OBJECT_finish:
8213    @bl      common_squeak0
8214    cmp     r9, #0                      @ check object for null
8215    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8216    beq     common_errNullObject        @ object was null
8217    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8218    mov     r2, rINST, lsr #8           @ r2<- A+
8219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8220    and     r2, r2, #15                 @ r2<- A
8221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8222    SET_VREG(r0, r2)                    @ fp[A]<- r0
8223    GOTO_OPCODE(ip)                     @ jump to next instruction
8224
8225
8226/* continuation for OP_IGET_BOOLEAN */
8227
8228    /*
8229     * Currently:
8230     *  r0 holds resolved field
8231     *  r9 holds object
8232     */
8233.LOP_IGET_BOOLEAN_finish:
8234    @bl      common_squeak1
8235    cmp     r9, #0                      @ check object for null
8236    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8237    beq     common_errNullObject        @ object was null
8238    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8239    mov     r2, rINST, lsr #8           @ r2<- A+
8240    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8241    and     r2, r2, #15                 @ r2<- A
8242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8243    SET_VREG(r0, r2)                    @ fp[A]<- r0
8244    GOTO_OPCODE(ip)                     @ jump to next instruction
8245
8246
8247/* continuation for OP_IGET_BYTE */
8248
8249    /*
8250     * Currently:
8251     *  r0 holds resolved field
8252     *  r9 holds object
8253     */
8254.LOP_IGET_BYTE_finish:
8255    @bl      common_squeak2
8256    cmp     r9, #0                      @ check object for null
8257    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8258    beq     common_errNullObject        @ object was null
8259    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8260    mov     r2, rINST, lsr #8           @ r2<- A+
8261    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8262    and     r2, r2, #15                 @ r2<- A
8263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8264    SET_VREG(r0, r2)                    @ fp[A]<- r0
8265    GOTO_OPCODE(ip)                     @ jump to next instruction
8266
8267
8268/* continuation for OP_IGET_CHAR */
8269
8270    /*
8271     * Currently:
8272     *  r0 holds resolved field
8273     *  r9 holds object
8274     */
8275.LOP_IGET_CHAR_finish:
8276    @bl      common_squeak3
8277    cmp     r9, #0                      @ check object for null
8278    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8279    beq     common_errNullObject        @ object was null
8280    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8281    mov     r2, rINST, lsr #8           @ r2<- A+
8282    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8283    and     r2, r2, #15                 @ r2<- A
8284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8285    SET_VREG(r0, r2)                    @ fp[A]<- r0
8286    GOTO_OPCODE(ip)                     @ jump to next instruction
8287
8288
8289/* continuation for OP_IGET_SHORT */
8290
8291    /*
8292     * Currently:
8293     *  r0 holds resolved field
8294     *  r9 holds object
8295     */
8296.LOP_IGET_SHORT_finish:
8297    @bl      common_squeak4
8298    cmp     r9, #0                      @ check object for null
8299    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8300    beq     common_errNullObject        @ object was null
8301    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8302    mov     r2, rINST, lsr #8           @ r2<- A+
8303    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8304    and     r2, r2, #15                 @ r2<- A
8305    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8306    SET_VREG(r0, r2)                    @ fp[A]<- r0
8307    GOTO_OPCODE(ip)                     @ jump to next instruction
8308
8309
8310/* continuation for OP_IPUT */
8311
8312    /*
8313     * Currently:
8314     *  r0 holds resolved field
8315     *  r9 holds object
8316     */
8317.LOP_IPUT_finish:
8318    @bl      common_squeak0
8319    mov     r1, rINST, lsr #8           @ r1<- A+
8320    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8321    and     r1, r1, #15                 @ r1<- A
8322    cmp     r9, #0                      @ check object for null
8323    GET_VREG(r0, r1)                    @ r0<- fp[A]
8324    beq     common_errNullObject        @ object was null
8325    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8327    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8328    GOTO_OPCODE(ip)                     @ jump to next instruction
8329
8330
8331/* continuation for OP_IPUT_WIDE */
8332
8333    /*
8334     * Currently:
8335     *  r0 holds resolved field
8336     *  r9 holds object
8337     */
8338.LOP_IPUT_WIDE_finish:
8339    mov     r2, rINST, lsr #8           @ r2<- A+
8340    cmp     r9, #0                      @ check object for null
8341    and     r2, r2, #15                 @ r2<- A
8342    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8343    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8344    beq     common_errNullObject        @ object was null
8345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8346    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8348    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8349    GOTO_OPCODE(ip)                     @ jump to next instruction
8350
8351
8352/* continuation for OP_IPUT_OBJECT */
8353
8354    /*
8355     * Currently:
8356     *  r0 holds resolved field
8357     *  r9 holds object
8358     */
8359.LOP_IPUT_OBJECT_finish:
8360    @bl      common_squeak0
8361    mov     r1, rINST, lsr #8           @ r1<- A+
8362    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8363    and     r1, r1, #15                 @ r1<- A
8364    cmp     r9, #0                      @ check object for null
8365    GET_VREG(r0, r1)                    @ r0<- fp[A]
8366    beq     common_errNullObject        @ object was null
8367    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8369    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8370    GOTO_OPCODE(ip)                     @ jump to next instruction
8371
8372
8373/* continuation for OP_IPUT_BOOLEAN */
8374
8375    /*
8376     * Currently:
8377     *  r0 holds resolved field
8378     *  r9 holds object
8379     */
8380.LOP_IPUT_BOOLEAN_finish:
8381    @bl      common_squeak1
8382    mov     r1, rINST, lsr #8           @ r1<- A+
8383    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8384    and     r1, r1, #15                 @ r1<- A
8385    cmp     r9, #0                      @ check object for null
8386    GET_VREG(r0, r1)                    @ r0<- fp[A]
8387    beq     common_errNullObject        @ object was null
8388    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8389    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8390    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8391    GOTO_OPCODE(ip)                     @ jump to next instruction
8392
8393
8394/* continuation for OP_IPUT_BYTE */
8395
8396    /*
8397     * Currently:
8398     *  r0 holds resolved field
8399     *  r9 holds object
8400     */
8401.LOP_IPUT_BYTE_finish:
8402    @bl      common_squeak2
8403    mov     r1, rINST, lsr #8           @ r1<- A+
8404    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8405    and     r1, r1, #15                 @ r1<- A
8406    cmp     r9, #0                      @ check object for null
8407    GET_VREG(r0, r1)                    @ r0<- fp[A]
8408    beq     common_errNullObject        @ object was null
8409    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8410    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8411    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8412    GOTO_OPCODE(ip)                     @ jump to next instruction
8413
8414
8415/* continuation for OP_IPUT_CHAR */
8416
8417    /*
8418     * Currently:
8419     *  r0 holds resolved field
8420     *  r9 holds object
8421     */
8422.LOP_IPUT_CHAR_finish:
8423    @bl      common_squeak3
8424    mov     r1, rINST, lsr #8           @ r1<- A+
8425    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8426    and     r1, r1, #15                 @ r1<- A
8427    cmp     r9, #0                      @ check object for null
8428    GET_VREG(r0, r1)                    @ r0<- fp[A]
8429    beq     common_errNullObject        @ object was null
8430    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8432    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8433    GOTO_OPCODE(ip)                     @ jump to next instruction
8434
8435
8436/* continuation for OP_IPUT_SHORT */
8437
8438    /*
8439     * Currently:
8440     *  r0 holds resolved field
8441     *  r9 holds object
8442     */
8443.LOP_IPUT_SHORT_finish:
8444    @bl      common_squeak4
8445    mov     r1, rINST, lsr #8           @ r1<- A+
8446    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8447    and     r1, r1, #15                 @ r1<- A
8448    cmp     r9, #0                      @ check object for null
8449    GET_VREG(r0, r1)                    @ r0<- fp[A]
8450    beq     common_errNullObject        @ object was null
8451    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8452    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8453    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8454    GOTO_OPCODE(ip)                     @ jump to next instruction
8455
8456
8457/* continuation for OP_SGET */
8458
8459    /*
8460     * Continuation if the field has not yet been resolved.
8461     *  r1: BBBB field ref
8462     */
8463.LOP_SGET_resolve:
8464    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8465    EXPORT_PC()                         @ resolve() could throw, so export now
8466    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8467    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8468    cmp     r0, #0                      @ success?
8469    bne     .LOP_SGET_finish          @ yes, finish
8470    b       common_exceptionThrown      @ no, handle exception
8471
8472
8473/* continuation for OP_SGET_WIDE */
8474
8475    /*
8476     * Continuation if the field has not yet been resolved.
8477     *  r1: BBBB field ref
8478     */
8479.LOP_SGET_WIDE_resolve:
8480    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8481    EXPORT_PC()                         @ resolve() could throw, so export now
8482    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8483    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8484    cmp     r0, #0                      @ success?
8485    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8486    b       common_exceptionThrown      @ no, handle exception
8487
8488
8489/* continuation for OP_SGET_OBJECT */
8490
8491    /*
8492     * Continuation if the field has not yet been resolved.
8493     *  r1: BBBB field ref
8494     */
8495.LOP_SGET_OBJECT_resolve:
8496    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8497    EXPORT_PC()                         @ resolve() could throw, so export now
8498    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8499    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8500    cmp     r0, #0                      @ success?
8501    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8502    b       common_exceptionThrown      @ no, handle exception
8503
8504
8505/* continuation for OP_SGET_BOOLEAN */
8506
8507    /*
8508     * Continuation if the field has not yet been resolved.
8509     *  r1: BBBB field ref
8510     */
8511.LOP_SGET_BOOLEAN_resolve:
8512    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8513    EXPORT_PC()                         @ resolve() could throw, so export now
8514    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8515    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8516    cmp     r0, #0                      @ success?
8517    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8518    b       common_exceptionThrown      @ no, handle exception
8519
8520
8521/* continuation for OP_SGET_BYTE */
8522
8523    /*
8524     * Continuation if the field has not yet been resolved.
8525     *  r1: BBBB field ref
8526     */
8527.LOP_SGET_BYTE_resolve:
8528    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8529    EXPORT_PC()                         @ resolve() could throw, so export now
8530    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8531    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8532    cmp     r0, #0                      @ success?
8533    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8534    b       common_exceptionThrown      @ no, handle exception
8535
8536
8537/* continuation for OP_SGET_CHAR */
8538
8539    /*
8540     * Continuation if the field has not yet been resolved.
8541     *  r1: BBBB field ref
8542     */
8543.LOP_SGET_CHAR_resolve:
8544    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8545    EXPORT_PC()                         @ resolve() could throw, so export now
8546    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8547    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8548    cmp     r0, #0                      @ success?
8549    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8550    b       common_exceptionThrown      @ no, handle exception
8551
8552
8553/* continuation for OP_SGET_SHORT */
8554
8555    /*
8556     * Continuation if the field has not yet been resolved.
8557     *  r1: BBBB field ref
8558     */
8559.LOP_SGET_SHORT_resolve:
8560    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8561    EXPORT_PC()                         @ resolve() could throw, so export now
8562    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8563    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8564    cmp     r0, #0                      @ success?
8565    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8566    b       common_exceptionThrown      @ no, handle exception
8567
8568
8569/* continuation for OP_SPUT */
8570
8571    /*
8572     * Continuation if the field has not yet been resolved.
8573     *  r1: BBBB field ref
8574     */
8575.LOP_SPUT_resolve:
8576    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8577    EXPORT_PC()                         @ resolve() could throw, so export now
8578    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8579    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8580    cmp     r0, #0                      @ success?
8581    bne     .LOP_SPUT_finish          @ yes, finish
8582    b       common_exceptionThrown      @ no, handle exception
8583
8584
8585/* continuation for OP_SPUT_WIDE */
8586
8587    /*
8588     * Continuation if the field has not yet been resolved.
8589     *  r1: BBBB field ref
8590     *  r9: &fp[AA]
8591     */
8592.LOP_SPUT_WIDE_resolve:
8593    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8594    EXPORT_PC()                         @ resolve() could throw, so export now
8595    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8596    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8597    cmp     r0, #0                      @ success?
8598    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8599    b       common_exceptionThrown      @ no, handle exception
8600
8601
8602/* continuation for OP_SPUT_OBJECT */
8603
8604    /*
8605     * Continuation if the field has not yet been resolved.
8606     *  r1: BBBB field ref
8607     */
8608.LOP_SPUT_OBJECT_resolve:
8609    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8610    EXPORT_PC()                         @ resolve() could throw, so export now
8611    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8612    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8613    cmp     r0, #0                      @ success?
8614    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8615    b       common_exceptionThrown      @ no, handle exception
8616
8617
8618/* continuation for OP_SPUT_BOOLEAN */
8619
8620    /*
8621     * Continuation if the field has not yet been resolved.
8622     *  r1: BBBB field ref
8623     */
8624.LOP_SPUT_BOOLEAN_resolve:
8625    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8626    EXPORT_PC()                         @ resolve() could throw, so export now
8627    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8628    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8629    cmp     r0, #0                      @ success?
8630    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8631    b       common_exceptionThrown      @ no, handle exception
8632
8633
8634/* continuation for OP_SPUT_BYTE */
8635
8636    /*
8637     * Continuation if the field has not yet been resolved.
8638     *  r1: BBBB field ref
8639     */
8640.LOP_SPUT_BYTE_resolve:
8641    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8642    EXPORT_PC()                         @ resolve() could throw, so export now
8643    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8644    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8645    cmp     r0, #0                      @ success?
8646    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8647    b       common_exceptionThrown      @ no, handle exception
8648
8649
8650/* continuation for OP_SPUT_CHAR */
8651
8652    /*
8653     * Continuation if the field has not yet been resolved.
8654     *  r1: BBBB field ref
8655     */
8656.LOP_SPUT_CHAR_resolve:
8657    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8658    EXPORT_PC()                         @ resolve() could throw, so export now
8659    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8660    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8661    cmp     r0, #0                      @ success?
8662    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8663    b       common_exceptionThrown      @ no, handle exception
8664
8665
8666/* continuation for OP_SPUT_SHORT */
8667
8668    /*
8669     * Continuation if the field has not yet been resolved.
8670     *  r1: BBBB field ref
8671     */
8672.LOP_SPUT_SHORT_resolve:
8673    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8674    EXPORT_PC()                         @ resolve() could throw, so export now
8675    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8676    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8677    cmp     r0, #0                      @ success?
8678    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8679    b       common_exceptionThrown      @ no, handle exception
8680
8681
8682/* continuation for OP_INVOKE_VIRTUAL */
8683
8684    /*
8685     * At this point:
8686     *  r0 = resolved base method
8687     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8688     */
8689.LOP_INVOKE_VIRTUAL_continue:
8690    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8691    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8692    cmp     r1, #0                      @ is "this" null?
8693    beq     common_errNullObject        @ null "this", throw exception
8694    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8695    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8696    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8697    bl      common_invokeMethodNoRange @ continue on
8698
8699
8700/* continuation for OP_INVOKE_SUPER */
8701
8702    /*
8703     * At this point:
8704     *  r0 = resolved base method
8705     *  r9 = method->clazz
8706     */
8707.LOP_INVOKE_SUPER_continue:
8708    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8709    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8710    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8711    EXPORT_PC()                         @ must export for invoke
8712    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8713    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8714    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8715    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8716    bl      common_invokeMethodNoRange @ continue on
8717
8718.LOP_INVOKE_SUPER_resolve:
8719    mov     r0, r9                      @ r0<- method->clazz
8720    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8721    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8722    cmp     r0, #0                      @ got null?
8723    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8724    b       common_exceptionThrown      @ yes, handle exception
8725
8726    /*
8727     * Throw a NoSuchMethodError with the method name as the message.
8728     *  r0 = resolved base method
8729     */
8730.LOP_INVOKE_SUPER_nsm:
8731    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8732    b       common_errNoSuchMethod
8733
8734
8735/* continuation for OP_INVOKE_DIRECT */
8736
8737    /*
8738     * On entry:
8739     *  r1 = reference (BBBB or CCCC)
8740     *  r10 = "this" register
8741     */
8742.LOP_INVOKE_DIRECT_resolve:
8743    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8744    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8745    mov     r2, #METHOD_DIRECT          @ resolver method type
8746    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8747    cmp     r0, #0                      @ got null?
8748    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8749    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8750    b       common_exceptionThrown      @ yes, handle exception
8751
8752
8753/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8754
8755    /*
8756     * At this point:
8757     *  r0 = resolved base method
8758     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8759     */
8760.LOP_INVOKE_VIRTUAL_RANGE_continue:
8761    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8762    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8763    cmp     r1, #0                      @ is "this" null?
8764    beq     common_errNullObject        @ null "this", throw exception
8765    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8766    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8767    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8768    bl      common_invokeMethodRange @ continue on
8769
8770
8771/* continuation for OP_INVOKE_SUPER_RANGE */
8772
8773    /*
8774     * At this point:
8775     *  r0 = resolved base method
8776     *  r9 = method->clazz
8777     */
8778.LOP_INVOKE_SUPER_RANGE_continue:
8779    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8780    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8781    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8782    EXPORT_PC()                         @ must export for invoke
8783    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8784    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8785    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8786    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8787    bl      common_invokeMethodRange @ continue on
8788
8789.LOP_INVOKE_SUPER_RANGE_resolve:
8790    mov     r0, r9                      @ r0<- method->clazz
8791    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8792    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8793    cmp     r0, #0                      @ got null?
8794    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8795    b       common_exceptionThrown      @ yes, handle exception
8796
8797    /*
8798     * Throw a NoSuchMethodError with the method name as the message.
8799     *  r0 = resolved base method
8800     */
8801.LOP_INVOKE_SUPER_RANGE_nsm:
8802    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8803    b       common_errNoSuchMethod
8804
8805
8806/* continuation for OP_INVOKE_DIRECT_RANGE */
8807
8808    /*
8809     * On entry:
8810     *  r1 = reference (BBBB or CCCC)
8811     *  r10 = "this" register
8812     */
8813.LOP_INVOKE_DIRECT_RANGE_resolve:
8814    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8815    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8816    mov     r2, #METHOD_DIRECT          @ resolver method type
8817    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8818    cmp     r0, #0                      @ got null?
8819    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8820    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8821    b       common_exceptionThrown      @ yes, handle exception
8822
8823
8824/* continuation for OP_FLOAT_TO_LONG */
8825/*
8826 * Convert the float in r0 to a long in r0/r1.
8827 *
8828 * We have to clip values to long min/max per the specification.  The
8829 * expected common case is a "reasonable" value that converts directly
8830 * to modest integer.  The EABI convert function isn't doing this for us.
8831 */
8832f2l_doconv:
8833    stmfd   sp!, {r4, lr}
8834    mov     r1, #0x5f000000             @ (float)maxlong
8835    mov     r4, r0
8836    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8837    cmp     r0, #0                      @ nonzero == yes
8838    mvnne   r0, #0                      @ return maxlong (7fffffff)
8839    mvnne   r1, #0x80000000
8840    ldmnefd sp!, {r4, pc}
8841
8842    mov     r0, r4                      @ recover arg
8843    mov     r1, #0xdf000000             @ (float)minlong
8844    bl      __aeabi_fcmple              @ is arg <= minlong?
8845    cmp     r0, #0                      @ nonzero == yes
8846    movne   r0, #0                      @ return minlong (80000000)
8847    movne   r1, #0x80000000
8848    ldmnefd sp!, {r4, pc}
8849
8850    mov     r0, r4                      @ recover arg
8851    mov     r1, r4
8852    bl      __aeabi_fcmpeq              @ is arg == self?
8853    cmp     r0, #0                      @ zero == no
8854    moveq   r1, #0                      @ return zero for NaN
8855    ldmeqfd sp!, {r4, pc}
8856
8857    mov     r0, r4                      @ recover arg
8858    bl      __aeabi_f2lz                @ convert float to long
8859    ldmfd   sp!, {r4, pc}
8860
8861
8862/* continuation for OP_DOUBLE_TO_LONG */
8863/*
8864 * Convert the double in r0/r1 to a long in r0/r1.
8865 *
8866 * We have to clip values to long min/max per the specification.  The
8867 * expected common case is a "reasonable" value that converts directly
8868 * to modest integer.  The EABI convert function isn't doing this for us.
8869 */
8870d2l_doconv:
8871    stmfd   sp!, {r4, r5, lr}           @ save regs
8872    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8873    add     r3, #0x00e00000             @  0x43e00000
8874    mov     r2, #0                      @ maxlong, as a double (low word)
8875    sub     sp, sp, #4                  @ align for EABI
8876    mov     r4, r0                      @ save a copy of r0
8877    mov     r5, r1                      @  and r1
8878    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8879    cmp     r0, #0                      @ nonzero == yes
8880    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8881    mvnne   r1, #0x80000000
8882    bne     1f
8883
8884    mov     r0, r4                      @ recover arg
8885    mov     r1, r5
8886    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8887    add     r3, #0x00e00000             @  0xc3e00000
8888    mov     r2, #0                      @ minlong, as a double (low word)
8889    bl      __aeabi_dcmple              @ is arg <= minlong?
8890    cmp     r0, #0                      @ nonzero == yes
8891    movne   r0, #0                      @ return minlong (8000000000000000)
8892    movne   r1, #0x80000000
8893    bne     1f
8894
8895    mov     r0, r4                      @ recover arg
8896    mov     r1, r5
8897    mov     r2, r4                      @ compare against self
8898    mov     r3, r5
8899    bl      __aeabi_dcmpeq              @ is arg == self?
8900    cmp     r0, #0                      @ zero == no
8901    moveq   r1, #0                      @ return zero for NaN
8902    beq     1f
8903
8904    mov     r0, r4                      @ recover arg
8905    mov     r1, r5
8906    bl      __aeabi_d2lz                @ convert double to long
8907
89081:
8909    add     sp, sp, #4
8910    ldmfd   sp!, {r4, r5, pc}
8911
8912
8913/* continuation for OP_MUL_LONG */
8914
8915.LOP_MUL_LONG_finish:
8916    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8917    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8918    GOTO_OPCODE(ip)                     @ jump to next instruction
8919
8920
8921/* continuation for OP_SHL_LONG */
8922
8923.LOP_SHL_LONG_finish:
8924    mov     r0, r0, asl r2              @  r0<- r0 << r2
8925    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8926    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8927    GOTO_OPCODE(ip)                     @ jump to next instruction
8928
8929
8930/* continuation for OP_SHR_LONG */
8931
8932.LOP_SHR_LONG_finish:
8933    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8935    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8936    GOTO_OPCODE(ip)                     @ jump to next instruction
8937
8938
8939/* continuation for OP_USHR_LONG */
8940
8941.LOP_USHR_LONG_finish:
8942    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8943    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8944    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8945    GOTO_OPCODE(ip)                     @ jump to next instruction
8946
8947
8948/* continuation for OP_SHL_LONG_2ADDR */
8949
8950.LOP_SHL_LONG_2ADDR_finish:
8951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8952    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8953    GOTO_OPCODE(ip)                     @ jump to next instruction
8954
8955
8956/* continuation for OP_SHR_LONG_2ADDR */
8957
8958.LOP_SHR_LONG_2ADDR_finish:
8959    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8960    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8961    GOTO_OPCODE(ip)                     @ jump to next instruction
8962
8963
8964/* continuation for OP_USHR_LONG_2ADDR */
8965
8966.LOP_USHR_LONG_2ADDR_finish:
8967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8968    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8969    GOTO_OPCODE(ip)                     @ jump to next instruction
8970
8971
8972/* continuation for OP_EXECUTE_INLINE */
8973
8974    /*
8975     * Extract args, call function.
8976     *  r0 = #of args (0-4)
8977     *  r10 = call index
8978     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8979     *
8980     * Other ideas:
8981     * - Use a jump table from the main piece to jump directly into the
8982     *   AND/LDR pairs.  Costs a data load, saves a branch.
8983     * - Have five separate pieces that do the loading, so we can work the
8984     *   interleave a little better.  Increases code size.
8985     */
8986.LOP_EXECUTE_INLINE_continue:
8987    rsb     r0, r0, #4                  @ r0<- 4-r0
8988    FETCH(r9, 2)                        @ r9<- FEDC
8989    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8990    bl      common_abort                @ (skipped due to ARM prefetch)
89914:  and     ip, r9, #0xf000             @ isolate F
8992    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89933:  and     ip, r9, #0x0f00             @ isolate E
8994    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89952:  and     ip, r9, #0x00f0             @ isolate D
8996    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
89971:  and     ip, r9, #0x000f             @ isolate C
8998    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
89990:
9000    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9001    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9002    @ (not reached)
9003
9004.LOP_EXECUTE_INLINE_table:
9005    .word   gDvmInlineOpsTable
9006
9007
9008/* continuation for OP_EXECUTE_INLINE_RANGE */
9009
9010    /*
9011     * Extract args, call function.
9012     *  r0 = #of args (0-4)
9013     *  r10 = call index
9014     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9015     */
9016.LOP_EXECUTE_INLINE_RANGE_continue:
9017    rsb     r0, r0, #4                  @ r0<- 4-r0
9018    FETCH(r9, 2)                        @ r9<- CCCC
9019    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9020    bl      common_abort                @ (skipped due to ARM prefetch)
90214:  add     ip, r9, #3                  @ base+3
9022    GET_VREG(r3, ip)                    @ r3<- vBase[3]
90233:  add     ip, r9, #2                  @ base+2
9024    GET_VREG(r2, ip)                    @ r2<- vBase[2]
90252:  add     ip, r9, #1                  @ base+1
9026    GET_VREG(r1, ip)                    @ r1<- vBase[1]
90271:  add     ip, r9, #0                  @ (nop)
9028    GET_VREG(r0, ip)                    @ r0<- vBase[0]
90290:
9030    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9031    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9032    @ (not reached)
9033
9034.LOP_EXECUTE_INLINE_RANGE_table:
9035    .word   gDvmInlineOpsTable
9036
9037
9038    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9039    .global dvmAsmSisterEnd
9040dvmAsmSisterEnd:
9041
9042/* File: armv5te/footer.S */
9043
9044/*
9045 * ===========================================================================
9046 *  Common subroutines and data
9047 * ===========================================================================
9048 */
9049
9050
9051
9052    .text
9053    .align  2
9054
9055#if defined(WITH_JIT)
9056#if defined(WITH_SELF_VERIFICATION)
9057    .global dvmJitToInterpPunt
9058dvmJitToInterpPunt:
9059    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9060    b      dvmJitSelfVerificationEnd    @ doesn't return
9061
9062    .global dvmJitToInterpSingleStep
9063dvmJitToInterpSingleStep:
9064    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9065    b      dvmJitSelfVerificationEnd    @ doesn't return
9066
9067    .global dvmJitToTraceSelect
9068dvmJitToTraceSelect:
9069    ldr    r0,[lr, #-1]                 @ pass our target PC
9070    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9071    b      dvmJitSelfVerificationEnd    @ doesn't return
9072
9073    .global dvmJitToBackwardBranch
9074dvmJitToBackwardBranch:
9075    ldr    r0,[lr, #-1]                 @ pass our target PC
9076    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9077    b      dvmJitSelfVerificationEnd    @ doesn't return
9078
9079    .global dvmJitToInterpNormal
9080dvmJitToInterpNormal:
9081    ldr    r0,[lr, #-1]                 @ pass our target PC
9082    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9083    b      dvmJitSelfVerificationEnd    @ doesn't return
9084
9085    .global dvmJitToInterpNoChain
9086dvmJitToInterpNoChain:
9087    mov    r0,rPC                       @ pass our target PC
9088    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9089    b      dvmJitSelfVerificationEnd    @ doesn't return
9090#else
9091/*
9092 * Return from the translation cache to the interpreter when the compiler is
9093 * having issues translating/executing a Dalvik instruction. We have to skip
9094 * the code cache lookup otherwise it is possible to indefinitely bouce
9095 * between the interpreter and the code cache if the instruction that fails
9096 * to be compiled happens to be at a trace start.
9097 */
9098    .global dvmJitToInterpPunt
9099dvmJitToInterpPunt:
9100    mov    rPC, r0
9101#ifdef EXIT_STATS
9102    mov    r0,lr
9103    bl     dvmBumpPunt;
9104#endif
9105    EXPORT_PC()
9106    adrl   rIBASE, dvmAsmInstructionStart
9107    FETCH_INST()
9108    GET_INST_OPCODE(ip)
9109    GOTO_OPCODE(ip)
9110
9111/*
9112 * Return to the interpreter to handle a single instruction.
9113 * On entry:
9114 *    r0 <= PC
9115 *    r1 <= PC of resume instruction
9116 *    lr <= resume point in translation
9117 */
9118    .global dvmJitToInterpSingleStep
9119dvmJitToInterpSingleStep:
9120    str    lr,[rGLUE,#offGlue_jitResume]
9121    str    r1,[rGLUE,#offGlue_jitResumePC]
9122    mov    r1,#kInterpEntryInstr
9123    @ enum is 4 byte in aapcs-EABI
9124    str    r1, [rGLUE, #offGlue_entryPoint]
9125    mov    rPC,r0
9126    EXPORT_PC()
9127    adrl   rIBASE, dvmAsmInstructionStart
9128    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9129    str    r2,[rGLUE,#offGlue_jitState]
9130    mov    r1,#1                  @ set changeInterp to bail to debug interp
9131    b      common_gotoBail
9132
9133
9134/*
9135 * Return from the translation cache and immediately request
9136 * a translation for the exit target.  Commonly used following
9137 * invokes.
9138 */
9139    .global dvmJitToTraceSelect
9140dvmJitToTraceSelect:
9141    ldr    rPC,[lr, #-1]           @ get our target PC
9142    add    rINST,lr,#-5            @ save start of chain branch
9143    mov    r0,rPC
9144    bl     dvmJitGetCodeAddr        @ Is there a translation?
9145    cmp    r0,#0
9146    beq    2f
9147    mov    r1,rINST
9148    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9149    mov    r1, rPC                  @ arg1 of translation may need this
9150    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9151    cmp    r0,#0                    @ successful chain?
9152    bxne   r0                       @ continue native execution
9153    b      toInterpreter            @ didn't chain - resume with interpreter
9154
9155/* No translation, so request one if profiling isn't disabled*/
91562:
9157    adrl   rIBASE, dvmAsmInstructionStart
9158    GET_JIT_PROF_TABLE(r0)
9159    FETCH_INST()
9160    cmp    r0, #0
9161    bne    common_selectTrace
9162    GET_INST_OPCODE(ip)
9163    GOTO_OPCODE(ip)
9164
9165/*
9166 * Return from the translation cache to the interpreter.
9167 * The return was done with a BLX from thumb mode, and
9168 * the following 32-bit word contains the target rPC value.
9169 * Note that lr (r14) will have its low-order bit set to denote
9170 * its thumb-mode origin.
9171 *
9172 * We'll need to stash our lr origin away, recover the new
9173 * target and then check to see if there is a translation available
9174 * for our new target.  If so, we do a translation chain and
9175 * go back to native execution.  Otherwise, it's back to the
9176 * interpreter (after treating this entry as a potential
9177 * trace start).
9178 */
9179    .global dvmJitToInterpNormal
9180dvmJitToInterpNormal:
9181    ldr    rPC,[lr, #-1]           @ get our target PC
9182    add    rINST,lr,#-5            @ save start of chain branch
9183#ifdef EXIT_STATS
9184    bl     dvmBumpNormal
9185#endif
9186    mov    r0,rPC
9187    bl     dvmJitGetCodeAddr        @ Is there a translation?
9188    cmp    r0,#0
9189    beq    toInterpreter            @ go if not, otherwise do chain
9190    mov    r1,rINST
9191    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9192    mov    r1, rPC                  @ arg1 of translation may need this
9193    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9194    cmp    r0,#0                    @ successful chain?
9195    bxne   r0                       @ continue native execution
9196    b      toInterpreter            @ didn't chain - resume with interpreter
9197
9198/*
9199 * Return from the translation cache to the interpreter to do method invocation.
9200 * Check if translation exists for the callee, but don't chain to it.
9201 */
9202    .global dvmJitToInterpNoChain
9203dvmJitToInterpNoChain:
9204#ifdef EXIT_STATS
9205    bl     dvmBumpNoChain
9206#endif
9207    mov    r0,rPC
9208    bl     dvmJitGetCodeAddr        @ Is there a translation?
9209    mov    r1, rPC                  @ arg1 of translation may need this
9210    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9211    cmp    r0,#0
9212    bxne   r0                       @ continue native execution if so
9213#endif
9214
9215/*
9216 * No translation, restore interpreter regs and start interpreting.
9217 * rGLUE & rFP were preserved in the translated code, and rPC has
9218 * already been restored by the time we get here.  We'll need to set
9219 * up rIBASE & rINST, and load the address of the JitTable into r0.
9220 */
9221toInterpreter:
9222    EXPORT_PC()
9223    adrl   rIBASE, dvmAsmInstructionStart
9224    FETCH_INST()
9225    GET_JIT_PROF_TABLE(r0)
9226    @ NOTE: intended fallthrough
9227/*
9228 * Common code to update potential trace start counter, and initiate
9229 * a trace-build if appropriate.  On entry, rPC should point to the
9230 * next instruction to execute, and rINST should be already loaded with
9231 * the next opcode word, and r0 holds a pointer to the jit profile
9232 * table (pJitProfTable).
9233 */
9234common_testUpdateProfile:
9235    cmp     r0,#0
9236    GET_INST_OPCODE(ip)
9237    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9238
9239common_updateProfile:
9240    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9241    lsl     r3,r3,#21          @ shift out excess 2047
9242    ldrb    r1,[r0,r3,lsr #21] @ get counter
9243    GET_INST_OPCODE(ip)
9244    subs    r1,r1,#1           @ decrement counter
9245    strb    r1,[r0,r3,lsr #21] @ and store it
9246    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9247
9248/*
9249 * Here, we switch to the debug interpreter to request
9250 * trace selection.  First, though, check to see if there
9251 * is already a native translation in place (and, if so,
9252 * jump to it now).
9253 */
9254    GET_JIT_THRESHOLD(r1)
9255    strb    r1,[r0,r3,lsr #21] @ reset counter
9256    EXPORT_PC()
9257    mov     r0,rPC
9258    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9259    mov    r1, rPC                      @ arg1 of translation may need this
9260    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
9261    cmp     r0,#0
9262#if !defined(WITH_SELF_VERIFICATION)
9263    bxne    r0                          @ jump to the translation
9264#else
9265    beq     common_selectTrace
9266    /*
9267     * At this point, we have a target translation.  However, if
9268     * that translation is actually the interpret-only pseudo-translation
9269     * we want to treat it the same as no translation.
9270     */
9271    mov     r10, r0                      @ save target
9272    bl      dvmCompilerGetInterpretTemplate
9273    cmp     r0, r10                      @ special case?
9274    bne     dvmJitSelfVerificationStart  @ set up self verification
9275    GET_INST_OPCODE(ip)
9276    GOTO_OPCODE(ip)
9277    /* no return */
9278#endif
9279
9280common_selectTrace:
9281    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9282    str     r2,[rGLUE,#offGlue_jitState]
9283    mov     r2,#kInterpEntryInstr       @ normal entry reason
9284    str     r2,[rGLUE,#offGlue_entryPoint]
9285    mov     r1,#1                       @ set changeInterp
9286    b       common_gotoBail
9287
9288#if defined(WITH_SELF_VERIFICATION)
9289/*
9290 * Save PC and registers to shadow memory for self verification mode
9291 * before jumping to native translation.
9292 * On entry, r10 contains the address of the target translation.
9293 */
9294dvmJitSelfVerificationStart:
9295    mov     r0,rPC                      @ r0<- program counter
9296    mov     r1,rFP                      @ r1<- frame pointer
9297    mov     r2,rGLUE                    @ r2<- InterpState pointer
9298    mov     r3,r10                      @ r3<- target translation
9299    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9300    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9301    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9302    bx      r10                         @ jump to the translation
9303
9304/*
9305 * Restore PC, registers, and interpState to original values
9306 * before jumping back to the interpreter.
9307 */
9308dvmJitSelfVerificationEnd:
9309    mov    r1,rFP                        @ pass ending fp
9310    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9311    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9312    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9313    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9314    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9315    cmp    r1,#0                         @ check for punt condition
9316    beq    1f
9317    mov    r2,#kJitSelfVerification      @ ask for self verification
9318    str    r2,[rGLUE,#offGlue_jitState]
9319    mov    r2,#kInterpEntryInstr         @ normal entry reason
9320    str    r2,[rGLUE,#offGlue_entryPoint]
9321    mov    r1,#1                         @ set changeInterp
9322    b      common_gotoBail
9323
93241:                                       @ exit to interpreter without check
9325    EXPORT_PC()
9326    adrl   rIBASE, dvmAsmInstructionStart
9327    FETCH_INST()
9328    GET_INST_OPCODE(ip)
9329    GOTO_OPCODE(ip)
9330#endif
9331
9332#endif
9333
9334/*
9335 * Common code when a backward branch is taken.
9336 *
9337 * On entry:
9338 *  r9 is PC adjustment *in bytes*
9339 */
9340common_backwardBranch:
9341    mov     r0, #kInterpEntryInstr
9342    bl      common_periodicChecks
9343#if defined(WITH_JIT)
9344    GET_JIT_PROF_TABLE(r0)
9345    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9346    cmp     r0,#0
9347    bne     common_updateProfile
9348    GET_INST_OPCODE(ip)
9349    GOTO_OPCODE(ip)
9350#else
9351    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9353    GOTO_OPCODE(ip)                     @ jump to next instruction
9354#endif
9355
9356
9357/*
9358 * Need to see if the thread needs to be suspended or debugger/profiler
9359 * activity has begun.
9360 *
9361 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9362 * have to do the second ldr.
9363 *
9364 * TODO: reduce this so we're just checking a single location.
9365 *
9366 * On entry:
9367 *  r0 is reentry type, e.g. kInterpEntryInstr
9368 *  r9 is trampoline PC adjustment *in bytes*
9369 */
9370common_periodicChecks:
9371    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9372
9373    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9374    str     r0, [rGLUE, #offGlue_entryPoint]
9375
9376#if defined(WITH_DEBUGGER)
9377    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9378#endif
9379#if defined(WITH_PROFILER)
9380    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9381#endif
9382
9383    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9384
9385#if defined(WITH_DEBUGGER)
9386    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9387#endif
9388#if defined (WITH_PROFILER)
9389    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9390#endif
9391
9392    cmp     r3, #0                      @ suspend pending?
9393    bne     2f                          @ yes, do full suspension check
9394
9395#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9396# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9397    orrs    r1, r1, r2                  @ r1<- r1 | r2
9398    cmp     r1, #0                      @ debugger attached or profiler started?
9399# elif defined(WITH_DEBUGGER)
9400    cmp     r1, #0                      @ debugger attached?
9401# elif defined(WITH_PROFILER)
9402    cmp     r2, #0                      @ profiler started?
9403# endif
9404    bne     3f                          @ debugger/profiler, switch interp
9405#endif
9406
9407    bx      lr                          @ nothing to do, return
9408
94092:  @ check suspend
9410    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9411    EXPORT_PC()                         @ need for precise GC
9412    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9413
94143:  @ debugger/profiler enabled, bail out
9415    add     rPC, rPC, r9                @ update rPC
9416    mov     r1, #1                      @ "want switch" = true
9417    b       common_gotoBail
9418
9419
9420/*
9421 * The equivalent of "goto bail", this calls through the "bail handler".
9422 *
9423 * State registers will be saved to the "glue" area before bailing.
9424 *
9425 * On entry:
9426 *  r1 is "bool changeInterp", indicating if we want to switch to the
9427 *     other interpreter or just bail all the way out
9428 */
9429common_gotoBail:
9430    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9431    mov     r0, rGLUE                   @ r0<- glue ptr
9432    b       dvmMterpStdBail             @ call(glue, changeInterp)
9433
9434    @add     r1, r1, #1                  @ using (boolean+1)
9435    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9436    @bl      _longjmp                    @ does not return
9437    @bl      common_abort
9438
9439
9440/*
9441 * Common code for method invocation with range.
9442 *
9443 * On entry:
9444 *  r0 is "Method* methodToCall", the method we're trying to call
9445 */
9446common_invokeMethodRange:
9447.LinvokeNewRange:
9448    @ prepare to copy args to "outs" area of current frame
9449    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9450    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9451    beq     .LinvokeArgsDone            @ if no args, skip the rest
9452    FETCH(r1, 2)                        @ r1<- CCCC
9453
9454    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9455    @ (very few methods have > 10 args; could unroll for common cases)
9456    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9457    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9458    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94591:  ldr     r1, [r3], #4                @ val = *fp++
9460    subs    r2, r2, #1                  @ count--
9461    str     r1, [r10], #4               @ *outs++ = val
9462    bne     1b                          @ ...while count != 0
9463    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9464    b       .LinvokeArgsDone
9465
9466/*
9467 * Common code for method invocation without range.
9468 *
9469 * On entry:
9470 *  r0 is "Method* methodToCall", the method we're trying to call
9471 */
9472common_invokeMethodNoRange:
9473.LinvokeNewNoRange:
9474    @ prepare to copy args to "outs" area of current frame
9475    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9476    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9477    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9478    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9479    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9480    beq     .LinvokeArgsDone
9481
9482    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9483.LinvokeNonRange:
9484    rsb     r2, r2, #5                  @ r2<- 5-r2
9485    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9486    bl      common_abort                @ (skipped due to ARM prefetch)
94875:  and     ip, rINST, #0x0f00          @ isolate A
9488    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9489    mov     r0, r0                      @ nop
9490    str     r2, [r10, #-4]!             @ *--outs = vA
94914:  and     ip, r1, #0xf000             @ isolate G
9492    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9493    mov     r0, r0                      @ nop
9494    str     r2, [r10, #-4]!             @ *--outs = vG
94953:  and     ip, r1, #0x0f00             @ isolate F
9496    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9497    mov     r0, r0                      @ nop
9498    str     r2, [r10, #-4]!             @ *--outs = vF
94992:  and     ip, r1, #0x00f0             @ isolate E
9500    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9501    mov     r0, r0                      @ nop
9502    str     r2, [r10, #-4]!             @ *--outs = vE
95031:  and     ip, r1, #0x000f             @ isolate D
9504    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9505    mov     r0, r0                      @ nop
9506    str     r2, [r10, #-4]!             @ *--outs = vD
95070:  @ fall through to .LinvokeArgsDone
9508
9509.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9510    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9511    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9512    @ find space for the new stack frame, check for overflow
9513    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9514    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9515    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9516@    bl      common_dumpRegs
9517    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9518    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9519    cmp     r3, r9                      @ bottom < interpStackEnd?
9520    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9521    blt     .LstackOverflow             @ yes, this frame will overflow stack
9522
9523    @ set up newSaveArea
9524#ifdef EASY_GDB
9525    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9526    str     ip, [r10, #offStackSaveArea_prevSave]
9527#endif
9528    str     rFP, [r10, #offStackSaveArea_prevFrame]
9529    str     rPC, [r10, #offStackSaveArea_savedPc]
9530#if defined(WITH_JIT)
9531    mov     r9, #0
9532    str     r9, [r10, #offStackSaveArea_returnAddr]
9533#endif
9534    str     r0, [r10, #offStackSaveArea_method]
9535    tst     r3, #ACC_NATIVE
9536    bne     .LinvokeNative
9537
9538    /*
9539    stmfd   sp!, {r0-r3}
9540    bl      common_printNewline
9541    mov     r0, rFP
9542    mov     r1, #0
9543    bl      dvmDumpFp
9544    ldmfd   sp!, {r0-r3}
9545    stmfd   sp!, {r0-r3}
9546    mov     r0, r1
9547    mov     r1, r10
9548    bl      dvmDumpFp
9549    bl      common_printNewline
9550    ldmfd   sp!, {r0-r3}
9551    */
9552
9553    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9554    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9555    mov     rPC, r2                         @ publish new rPC
9556    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9557
9558    @ Update "glue" values for the new method
9559    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9560    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9561    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9562#if defined(WITH_JIT)
9563    GET_JIT_PROF_TABLE(r0)
9564    mov     rFP, r1                         @ fp = newFp
9565    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9566    mov     rINST, r9                       @ publish new rINST
9567    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9568    cmp     r0,#0
9569    bne     common_updateProfile
9570    GOTO_OPCODE(ip)                         @ jump to next instruction
9571#else
9572    mov     rFP, r1                         @ fp = newFp
9573    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9574    mov     rINST, r9                       @ publish new rINST
9575    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9576    GOTO_OPCODE(ip)                         @ jump to next instruction
9577#endif
9578
9579.LinvokeNative:
9580    @ Prep for the native call
9581    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9582    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9583    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9584    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9585    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9586    mov     r9, r3                      @ r9<- glue->self (preserve)
9587
9588    mov     r2, r0                      @ r2<- methodToCall
9589    mov     r0, r1                      @ r0<- newFp (points to args)
9590    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9591
9592#ifdef ASSIST_DEBUGGER
9593    /* insert fake function header to help gdb find the stack frame */
9594    b       .Lskip
9595    .type   dalvik_mterp, %function
9596dalvik_mterp:
9597    .fnstart
9598    MTERP_ENTRY1
9599    MTERP_ENTRY2
9600.Lskip:
9601#endif
9602
9603    @mov     lr, pc                      @ set return addr
9604    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9605    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9606
9607    @ native return; r9=self, r10=newSaveArea
9608    @ equivalent to dvmPopJniLocals
9609    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9610    ldr     r1, [r9, #offThread_exception] @ check for exception
9611    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9612    cmp     r1, #0                      @ null?
9613    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9614    bne     common_exceptionThrown      @ no, handle exception
9615
9616    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9617    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9618    GOTO_OPCODE(ip)                     @ jump to next instruction
9619
9620.LstackOverflow:    @ r0=methodToCall
9621    mov     r1, r0                      @ r1<- methodToCall
9622    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9623    bl      dvmHandleStackOverflow
9624    b       common_exceptionThrown
9625#ifdef ASSIST_DEBUGGER
9626    .fnend
9627#endif
9628
9629
9630    /*
9631     * Common code for method invocation, calling through "glue code".
9632     *
9633     * TODO: now that we have range and non-range invoke handlers, this
9634     *       needs to be split into two.  Maybe just create entry points
9635     *       that set r9 and jump here?
9636     *
9637     * On entry:
9638     *  r0 is "Method* methodToCall", the method we're trying to call
9639     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9640     */
9641     .if    0
9642.LinvokeOld:
9643    sub     sp, sp, #8                  @ space for args + pad
9644    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9645    mov     r2, r0                      @ A2<- methodToCall
9646    mov     r0, rGLUE                   @ A0<- glue
9647    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9648    mov     r1, r9                      @ A1<- methodCallRange
9649    mov     r3, rINST, lsr #8           @ A3<- AA
9650    str     ip, [sp, #0]                @ A4<- ip
9651    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9652    add     sp, sp, #8                  @ remove arg area
9653    b       common_resumeAfterGlueCall  @ continue to next instruction
9654    .endif
9655
9656
9657
9658/*
9659 * Common code for handling a return instruction.
9660 *
9661 * This does not return.
9662 */
9663common_returnFromMethod:
9664.LreturnNew:
9665    mov     r0, #kInterpEntryReturn
9666    mov     r9, #0
9667    bl      common_periodicChecks
9668
9669    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9670    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9671    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9672    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9673                                        @ r2<- method we're returning to
9674    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9675    cmp     r2, #0                      @ is this a break frame?
9676    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9677    mov     r1, #0                      @ "want switch" = false
9678    beq     common_gotoBail             @ break frame, bail out completely
9679
9680    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9681    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9682    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9683    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9684#if defined(WITH_JIT)
9685    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
9686    GET_JIT_PROF_TABLE(r0)
9687    mov     rPC, r9                     @ publish new rPC
9688    str     r1, [rGLUE, #offGlue_methodClassDex]
9689    cmp     r3, #0                      @ caller is compiled code
9690    blxne   r3
9691    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9692    cmp     r0,#0
9693    bne     common_updateProfile
9694    GOTO_OPCODE(ip)                     @ jump to next instruction
9695#else
9696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9697    mov     rPC, r9                     @ publish new rPC
9698    str     r1, [rGLUE, #offGlue_methodClassDex]
9699    GOTO_OPCODE(ip)                     @ jump to next instruction
9700#endif
9701
9702    /*
9703     * Return handling, calls through "glue code".
9704     */
9705     .if    0
9706.LreturnOld:
9707    SAVE_PC_FP_TO_GLUE()                @ export state
9708    mov     r0, rGLUE                   @ arg to function
9709    bl      dvmMterp_returnFromMethod
9710    b       common_resumeAfterGlueCall
9711    .endif
9712
9713
9714/*
9715 * Somebody has thrown an exception.  Handle it.
9716 *
9717 * If the exception processing code returns to us (instead of falling
9718 * out of the interpreter), continue with whatever the next instruction
9719 * now happens to be.
9720 *
9721 * This does not return.
9722 */
9723     .global dvmMterpCommonExceptionThrown
9724dvmMterpCommonExceptionThrown:
9725common_exceptionThrown:
9726.LexceptionNew:
9727    mov     r0, #kInterpEntryThrow
9728    mov     r9, #0
9729    bl      common_periodicChecks
9730
9731#if defined(WITH_JIT)
9732    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9733    str     r2,[rGLUE,#offGlue_jitState]
9734#endif
9735
9736    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9737    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9738    mov     r1, r10                     @ r1<- self
9739    mov     r0, r9                      @ r0<- exception
9740    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9741    mov     r3, #0                      @ r3<- NULL
9742    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9743
9744    /* set up args and a local for "&fp" */
9745    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9746    str     rFP, [sp, #-4]!             @ *--sp = fp
9747    mov     ip, sp                      @ ip<- &fp
9748    mov     r3, #0                      @ r3<- false
9749    str     ip, [sp, #-4]!              @ *--sp = &fp
9750    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9751    mov     r0, r10                     @ r0<- self
9752    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9753    mov     r2, r9                      @ r2<- exception
9754    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9755    mov     r1, r1, asr #1              @ r1<- offset in code units
9756
9757    /* call, r0 gets catchRelPc (a code-unit offset) */
9758    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9759
9760    /* fix earlier stack overflow if necessary; may trash rFP */
9761    ldrb    r1, [r10, #offThread_stackOverflowed]
9762    cmp     r1, #0                      @ did we overflow earlier?
9763    beq     1f                          @ no, skip ahead
9764    mov     rFP, r0                     @ save relPc result in rFP
9765    mov     r0, r10                     @ r0<- self
9766    bl      dvmCleanupStackOverflow     @ call(self)
9767    mov     r0, rFP                     @ restore result
97681:
9769
9770    /* update frame pointer and check result from dvmFindCatchBlock */
9771    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9772    cmp     r0, #0                      @ is catchRelPc < 0?
9773    add     sp, sp, #8                  @ restore stack
9774    bmi     .LnotCaughtLocally
9775
9776    /* adjust locals to match self->curFrame and updated PC */
9777    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9778    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9779    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9780    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9781    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9782    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9783    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9784    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9785
9786    /* release the tracked alloc on the exception */
9787    mov     r0, r9                      @ r0<- exception
9788    mov     r1, r10                     @ r1<- self
9789    bl      dvmReleaseTrackedAlloc      @ release the exception
9790
9791    /* restore the exception if the handler wants it */
9792    FETCH_INST()                        @ load rINST from rPC
9793    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9794    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9795    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9796    GOTO_OPCODE(ip)                     @ jump to next instruction
9797
9798.LnotCaughtLocally: @ r9=exception, r10=self
9799    /* fix stack overflow if necessary */
9800    ldrb    r1, [r10, #offThread_stackOverflowed]
9801    cmp     r1, #0                      @ did we overflow earlier?
9802    movne   r0, r10                     @ if yes: r0<- self
9803    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9804
9805    @ may want to show "not caught locally" debug messages here
9806#if DVM_SHOW_EXCEPTION >= 2
9807    /* call __android_log_print(prio, tag, format, ...) */
9808    /* "Exception %s from %s:%d not caught locally" */
9809    @ dvmLineNumFromPC(method, pc - method->insns)
9810    ldr     r0, [rGLUE, #offGlue_method]
9811    ldr     r1, [r0, #offMethod_insns]
9812    sub     r1, rPC, r1
9813    asr     r1, r1, #1
9814    bl      dvmLineNumFromPC
9815    str     r0, [sp, #-4]!
9816    @ dvmGetMethodSourceFile(method)
9817    ldr     r0, [rGLUE, #offGlue_method]
9818    bl      dvmGetMethodSourceFile
9819    str     r0, [sp, #-4]!
9820    @ exception->clazz->descriptor
9821    ldr     r3, [r9, #offObject_clazz]
9822    ldr     r3, [r3, #offClassObject_descriptor]
9823    @
9824    ldr     r2, strExceptionNotCaughtLocally
9825    ldr     r1, strLogTag
9826    mov     r0, #3                      @ LOG_DEBUG
9827    bl      __android_log_print
9828#endif
9829    str     r9, [r10, #offThread_exception] @ restore exception
9830    mov     r0, r9                      @ r0<- exception
9831    mov     r1, r10                     @ r1<- self
9832    bl      dvmReleaseTrackedAlloc      @ release the exception
9833    mov     r1, #0                      @ "want switch" = false
9834    b       common_gotoBail             @ bail out
9835
9836
9837    /*
9838     * Exception handling, calls through "glue code".
9839     */
9840    .if     0
9841.LexceptionOld:
9842    SAVE_PC_FP_TO_GLUE()                @ export state
9843    mov     r0, rGLUE                   @ arg to function
9844    bl      dvmMterp_exceptionThrown
9845    b       common_resumeAfterGlueCall
9846    .endif
9847
9848
9849/*
9850 * After returning from a "glued" function, pull out the updated
9851 * values and start executing at the next instruction.
9852 */
9853common_resumeAfterGlueCall:
9854    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9855    FETCH_INST()                        @ load rINST from rPC
9856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9857    GOTO_OPCODE(ip)                     @ jump to next instruction
9858
9859/*
9860 * Invalid array index.
9861 */
9862common_errArrayIndex:
9863    EXPORT_PC()
9864    ldr     r0, strArrayIndexException
9865    mov     r1, #0
9866    bl      dvmThrowException
9867    b       common_exceptionThrown
9868
9869/*
9870 * Invalid array value.
9871 */
9872common_errArrayStore:
9873    EXPORT_PC()
9874    ldr     r0, strArrayStoreException
9875    mov     r1, #0
9876    bl      dvmThrowException
9877    b       common_exceptionThrown
9878
9879/*
9880 * Integer divide or mod by zero.
9881 */
9882common_errDivideByZero:
9883    EXPORT_PC()
9884    ldr     r0, strArithmeticException
9885    ldr     r1, strDivideByZero
9886    bl      dvmThrowException
9887    b       common_exceptionThrown
9888
9889/*
9890 * Attempt to allocate an array with a negative size.
9891 */
9892common_errNegativeArraySize:
9893    EXPORT_PC()
9894    ldr     r0, strNegativeArraySizeException
9895    mov     r1, #0
9896    bl      dvmThrowException
9897    b       common_exceptionThrown
9898
9899/*
9900 * Invocation of a non-existent method.
9901 */
9902common_errNoSuchMethod:
9903    EXPORT_PC()
9904    ldr     r0, strNoSuchMethodError
9905    mov     r1, #0
9906    bl      dvmThrowException
9907    b       common_exceptionThrown
9908
9909/*
9910 * We encountered a null object when we weren't expecting one.  We
9911 * export the PC, throw a NullPointerException, and goto the exception
9912 * processing code.
9913 */
9914common_errNullObject:
9915    EXPORT_PC()
9916    ldr     r0, strNullPointerException
9917    mov     r1, #0
9918    bl      dvmThrowException
9919    b       common_exceptionThrown
9920
9921/*
9922 * For debugging, cause an immediate fault.  The source address will
9923 * be in lr (use a bl instruction to jump here).
9924 */
9925common_abort:
9926    ldr     pc, .LdeadFood
9927.LdeadFood:
9928    .word   0xdeadf00d
9929
9930/*
9931 * Spit out a "we were here", preserving all registers.  (The attempt
9932 * to save ip won't work, but we need to save an even number of
9933 * registers for EABI 64-bit stack alignment.)
9934 */
9935    .macro  SQUEAK num
9936common_squeak\num:
9937    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9938    ldr     r0, strSqueak
9939    mov     r1, #\num
9940    bl      printf
9941    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9942    bx      lr
9943    .endm
9944
9945    SQUEAK  0
9946    SQUEAK  1
9947    SQUEAK  2
9948    SQUEAK  3
9949    SQUEAK  4
9950    SQUEAK  5
9951
9952/*
9953 * Spit out the number in r0, preserving registers.
9954 */
9955common_printNum:
9956    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9957    mov     r1, r0
9958    ldr     r0, strSqueak
9959    bl      printf
9960    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9961    bx      lr
9962
9963/*
9964 * Print a newline, preserving registers.
9965 */
9966common_printNewline:
9967    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9968    ldr     r0, strNewline
9969    bl      printf
9970    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9971    bx      lr
9972
9973    /*
9974     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9975     */
9976common_printHex:
9977    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9978    mov     r1, r0
9979    ldr     r0, strPrintHex
9980    bl      printf
9981    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9982    bx      lr
9983
9984/*
9985 * Print the 64-bit quantity in r0-r1, preserving registers.
9986 */
9987common_printLong:
9988    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9989    mov     r3, r1
9990    mov     r2, r0
9991    ldr     r0, strPrintLong
9992    bl      printf
9993    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9994    bx      lr
9995
9996/*
9997 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9998 */
9999common_printMethod:
10000    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10001    bl      dvmMterpPrintMethod
10002    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10003    bx      lr
10004
10005/*
10006 * Call a C helper function that dumps regs and possibly some
10007 * additional info.  Requires the C function to be compiled in.
10008 */
10009    .if     0
10010common_dumpRegs:
10011    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10012    bl      dvmMterpDumpArmRegs
10013    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10014    bx      lr
10015    .endif
10016
10017#if 0
10018/*
10019 * Experiment on VFP mode.
10020 *
10021 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10022 *
10023 * Updates the bits specified by "mask", setting them to the values in "val".
10024 */
10025setFPSCR:
10026    and     r0, r0, r1                  @ make sure no stray bits are set
10027    fmrx    r2, fpscr                   @ get VFP reg
10028    mvn     r1, r1                      @ bit-invert mask
10029    and     r2, r2, r1                  @ clear masked bits
10030    orr     r2, r2, r0                  @ set specified bits
10031    fmxr    fpscr, r2                   @ set VFP reg
10032    mov     r0, r2                      @ return new value
10033    bx      lr
10034
10035    .align  2
10036    .global dvmConfigureFP
10037    .type   dvmConfigureFP, %function
10038dvmConfigureFP:
10039    stmfd   sp!, {ip, lr}
10040    /* 0x03000000 sets DN/FZ */
10041    /* 0x00009f00 clears the six exception enable flags */
10042    bl      common_squeak0
10043    mov     r0, #0x03000000             @ r0<- 0x03000000
10044    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10045    bl      setFPSCR
10046    ldmfd   sp!, {ip, pc}
10047#endif
10048
10049
10050/*
10051 * String references, must be close to the code that uses them.
10052 */
10053    .align  2
10054strArithmeticException:
10055    .word   .LstrArithmeticException
10056strArrayIndexException:
10057    .word   .LstrArrayIndexException
10058strArrayStoreException:
10059    .word   .LstrArrayStoreException
10060strDivideByZero:
10061    .word   .LstrDivideByZero
10062strNegativeArraySizeException:
10063    .word   .LstrNegativeArraySizeException
10064strNoSuchMethodError:
10065    .word   .LstrNoSuchMethodError
10066strNullPointerException:
10067    .word   .LstrNullPointerException
10068
10069strLogTag:
10070    .word   .LstrLogTag
10071strExceptionNotCaughtLocally:
10072    .word   .LstrExceptionNotCaughtLocally
10073
10074strNewline:
10075    .word   .LstrNewline
10076strSqueak:
10077    .word   .LstrSqueak
10078strPrintHex:
10079    .word   .LstrPrintHex
10080strPrintLong:
10081    .word   .LstrPrintLong
10082
10083/*
10084 * Zero-terminated ASCII string data.
10085 *
10086 * On ARM we have two choices: do like gcc does, and LDR from a .word
10087 * with the address, or use an ADR pseudo-op to get the address
10088 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10089 * PC-relative addressing mode and hence has a limited range, which
10090 * makes it not work well with mergeable string sections.
10091 */
10092    .section .rodata.str1.4,"aMS",%progbits,1
10093
10094.LstrBadEntryPoint:
10095    .asciz  "Bad entry point %d\n"
10096.LstrArithmeticException:
10097    .asciz  "Ljava/lang/ArithmeticException;"
10098.LstrArrayIndexException:
10099    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10100.LstrArrayStoreException:
10101    .asciz  "Ljava/lang/ArrayStoreException;"
10102.LstrClassCastException:
10103    .asciz  "Ljava/lang/ClassCastException;"
10104.LstrDivideByZero:
10105    .asciz  "divide by zero"
10106.LstrFilledNewArrayNotImpl:
10107    .asciz  "filled-new-array only implemented for objects and 'int'"
10108.LstrInternalError:
10109    .asciz  "Ljava/lang/InternalError;"
10110.LstrInstantiationError:
10111    .asciz  "Ljava/lang/InstantiationError;"
10112.LstrNegativeArraySizeException:
10113    .asciz  "Ljava/lang/NegativeArraySizeException;"
10114.LstrNoSuchMethodError:
10115    .asciz  "Ljava/lang/NoSuchMethodError;"
10116.LstrNullPointerException:
10117    .asciz  "Ljava/lang/NullPointerException;"
10118
10119.LstrLogTag:
10120    .asciz  "mterp"
10121.LstrExceptionNotCaughtLocally:
10122    .asciz  "Exception %s from %s:%d not caught locally\n"
10123
10124.LstrNewline:
10125    .asciz  "\n"
10126.LstrSqueak:
10127    .asciz  "<%d>"
10128.LstrPrintHex:
10129    .asciz  "<0x%x>"
10130.LstrPrintLong:
10131    .asciz  "<%lld>"
10132
10133
10134