InterpAsm-armv5te-vfp.S revision 72e93344b4d1ffc71e9c832ec23de0657e5b04a5
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_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
189#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204
205/* File: armv5te/platform.S */
206/*
207 * ===========================================================================
208 *  CPU-version-specific defines
209 * ===========================================================================
210 */
211
212/*
213 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
214 * one-way branch.
215 *
216 * May modify IP.  Does not modify LR.
217 */
218.macro  LDR_PC source
219    ldr     pc, \source
220.endm
221
222/*
223 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
224 * Jump to subroutine.
225 *
226 * May modify IP and LR.
227 */
228.macro  LDR_PC_LR source
229    mov     lr, pc
230    ldr     pc, \source
231.endm
232
233/*
234 * Macro for "LDMFD SP!, {...regs...,PC}".
235 *
236 * May modify IP and LR.
237 */
238.macro  LDMFD_PC regs
239    ldmfd   sp!, {\regs,pc}
240.endm
241
242
243/* File: armv5te/entry.S */
244/*
245 * Copyright (C) 2008 The Android Open Source Project
246 *
247 * Licensed under the Apache License, Version 2.0 (the "License");
248 * you may not use this file except in compliance with the License.
249 * You may obtain a copy of the License at
250 *
251 *      http://www.apache.org/licenses/LICENSE-2.0
252 *
253 * Unless required by applicable law or agreed to in writing, software
254 * distributed under the License is distributed on an "AS IS" BASIS,
255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
256 * See the License for the specific language governing permissions and
257 * limitations under the License.
258 */
259/*
260 * Interpreter entry point.
261 */
262
263/*
264 * We don't have formal stack frames, so gdb scans upward in the code
265 * to find the start of the function (a label with the %function type),
266 * and then looks at the next few instructions to figure out what
267 * got pushed onto the stack.  From this it figures out how to restore
268 * the registers, including PC, for the previous stack frame.  If gdb
269 * sees a non-function label, it stops scanning, so either we need to
270 * have nothing but assembler-local labels between the entry point and
271 * the break, or we need to fake it out.
272 *
273 * When this is defined, we add some stuff to make gdb less confused.
274 */
275#define ASSIST_DEBUGGER 1
276
277    .text
278    .align  2
279    .global dvmMterpStdRun
280    .type   dvmMterpStdRun, %function
281
282/*
283 * On entry:
284 *  r0  MterpGlue* glue
285 *
286 * This function returns a boolean "changeInterp" value.  The return comes
287 * via a call to dvmMterpStdBail().
288 */
289dvmMterpStdRun:
290#define MTERP_ENTRY1 \
291    .save {r4-r10,fp,lr}; \
292    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
293#define MTERP_ENTRY2 \
294    .pad    #4; \
295    sub     sp, sp, #4                  @ align 64
296
297    .fnstart
298    MTERP_ENTRY1
299    MTERP_ENTRY2
300
301    /* save stack pointer, add magic word for debuggerd */
302    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
303
304    /* set up "named" registers, figure out entry point */
305    mov     rGLUE, r0                   @ set rGLUE
306    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
307    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
308    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
309    cmp     r1, #kInterpEntryInstr      @ usual case?
310    bne     .Lnot_instr                 @ no, handle it
311
312#if defined(WITH_JIT)
313.Lno_singleStep:
314    /* Entry is always a possible trace start */
315    GET_JIT_PROF_TABLE(r0)
316    FETCH_INST()
317    cmp    r0,#0
318    bne    common_updateProfile
319    GET_INST_OPCODE(ip)
320    GOTO_OPCODE(ip)
321#else
322    /* start executing the instruction at rPC */
323    FETCH_INST()                        @ load rINST from rPC
324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
325    GOTO_OPCODE(ip)                     @ jump to next instruction
326#endif
327
328.Lnot_instr:
329    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
330    beq     common_returnFromMethod
331
332.Lnot_return:
333    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
334    beq     common_exceptionThrown
335
336#if defined(WITH_JIT)
337.Lnot_throw:
338    ldr     r0,[rGLUE, #offGlue_jitResume]
339    ldr     r2,[rGLUE, #offGlue_jitResumePC]
340    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
341    bne     .Lbad_arg
342    cmp     rPC,r2
343    bne     .Lno_singleStep             @ must have branched, don't resume
344    mov     r1, #kInterpEntryInstr
345    strb    r1, [rGLUE, #offGlue_entryPoint]
346    ldr     rINST, .LdvmCompilerTemplate
347    bx      r0                          @ re-enter the translation
348.LdvmCompilerTemplate:
349    .word   dvmCompilerTemplateStart
350#endif
351
352.Lbad_arg:
353    ldr     r0, strBadEntryPoint
354    @ r1 holds value of entryPoint
355    bl      printf
356    bl      dvmAbort
357    .fnend
358
359
360    .global dvmMterpStdBail
361    .type   dvmMterpStdBail, %function
362
363/*
364 * Restore the stack pointer and PC from the save point established on entry.
365 * This is essentially the same as a longjmp, but should be cheaper.  The
366 * last instruction causes us to return to whoever called dvmMterpStdRun.
367 *
368 * We pushed some registers on the stack in dvmMterpStdRun, then saved
369 * SP and LR.  Here we restore SP, restore the registers, and then restore
370 * LR to PC.
371 *
372 * On entry:
373 *  r0  MterpGlue* glue
374 *  r1  bool changeInterp
375 */
376dvmMterpStdBail:
377    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
378    mov     r0, r1                          @ return the changeInterp value
379    add     sp, sp, #4                      @ un-align 64
380    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
381
382
383/*
384 * String references.
385 */
386strBadEntryPoint:
387    .word   .LstrBadEntryPoint
388
389
390
391    .global dvmAsmInstructionStart
392    .type   dvmAsmInstructionStart, %function
393dvmAsmInstructionStart = .L_OP_NOP
394    .text
395
396/* ------------------------------ */
397    .balign 64
398.L_OP_NOP: /* 0x00 */
399/* File: armv5te/OP_NOP.S */
400    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
401    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
402    GOTO_OPCODE(ip)                     @ execute it
403
404#ifdef ASSIST_DEBUGGER
405    /* insert fake function header to help gdb find the stack frame */
406    .type   dalvik_inst, %function
407dalvik_inst:
408    .fnstart
409    MTERP_ENTRY1
410    MTERP_ENTRY2
411    .fnend
412#endif
413
414
415/* ------------------------------ */
416    .balign 64
417.L_OP_MOVE: /* 0x01 */
418/* File: 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_UNUSED_EC: /* 0xec */
7281/* File: armv5te/OP_UNUSED_EC.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:
7313     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
7314     *
7315     * The first four args are in r0-r3, but the last two must be pushed
7316     * onto the stack.
7317     */
7318    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7319    FETCH(r10, 1)                       @ r10<- BBBB
7320    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7321    EXPORT_PC()                         @ can throw
7322    sub     sp, sp, #8                  @ make room for arg(s)
7323    mov     r0, rINST, lsr #12          @ r0<- B
7324    str     r1, [sp]                    @ push &glue->retval
7325    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7326    add     sp, sp, #8                  @ pop stack
7327    cmp     r0, #0                      @ test boolean result of inline
7328    beq     common_exceptionThrown      @ returned false, handle exception
7329    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7331    GOTO_OPCODE(ip)                     @ jump to next instruction
7332
7333/* ------------------------------ */
7334    .balign 64
7335.L_OP_UNUSED_EF: /* 0xef */
7336/* File: armv5te/OP_UNUSED_EF.S */
7337/* File: armv5te/unused.S */
7338    bl      common_abort
7339
7340
7341
7342/* ------------------------------ */
7343    .balign 64
7344.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7345/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7346    /*
7347     * invoke-direct-empty is a no-op in a "standard" interpreter.
7348     */
7349    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7350    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7351    GOTO_OPCODE(ip)                     @ execute it
7352
7353/* ------------------------------ */
7354    .balign 64
7355.L_OP_UNUSED_F1: /* 0xf1 */
7356/* File: armv5te/OP_UNUSED_F1.S */
7357/* File: armv5te/unused.S */
7358    bl      common_abort
7359
7360
7361
7362/* ------------------------------ */
7363    .balign 64
7364.L_OP_IGET_QUICK: /* 0xf2 */
7365/* File: armv5te/OP_IGET_QUICK.S */
7366    /* For: iget-quick, iget-object-quick */
7367    /* op vA, vB, offset@CCCC */
7368    mov     r2, rINST, lsr #12          @ r2<- B
7369    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7370    FETCH(r1, 1)                        @ r1<- field byte offset
7371    cmp     r3, #0                      @ check object for null
7372    mov     r2, rINST, lsr #8           @ r2<- A(+)
7373    beq     common_errNullObject        @ object was null
7374    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7375    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7376    and     r2, r2, #15
7377    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7378    SET_VREG(r0, r2)                    @ fp[A]<- r0
7379    GOTO_OPCODE(ip)                     @ jump to next instruction
7380
7381
7382/* ------------------------------ */
7383    .balign 64
7384.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7385/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7386    /* iget-wide-quick vA, vB, offset@CCCC */
7387    mov     r2, rINST, lsr #12          @ r2<- B
7388    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7389    FETCH(r1, 1)                        @ r1<- field byte offset
7390    cmp     r3, #0                      @ check object for null
7391    mov     r2, rINST, lsr #8           @ r2<- A(+)
7392    beq     common_errNullObject        @ object was null
7393    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7394    and     r2, r2, #15
7395    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7396    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7397    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7398    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7399    GOTO_OPCODE(ip)                     @ jump to next instruction
7400
7401
7402/* ------------------------------ */
7403    .balign 64
7404.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7405/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7406/* File: armv5te/OP_IGET_QUICK.S */
7407    /* For: iget-quick, iget-object-quick */
7408    /* op 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    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7416    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7417    and     r2, r2, #15
7418    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7419    SET_VREG(r0, r2)                    @ fp[A]<- r0
7420    GOTO_OPCODE(ip)                     @ jump to next instruction
7421
7422
7423
7424/* ------------------------------ */
7425    .balign 64
7426.L_OP_IPUT_QUICK: /* 0xf5 */
7427/* File: armv5te/OP_IPUT_QUICK.S */
7428    /* For: iput-quick, iput-object-quick */
7429    /* op vA, vB, offset@CCCC */
7430    mov     r2, rINST, lsr #12          @ r2<- B
7431    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7432    FETCH(r1, 1)                        @ r1<- field byte offset
7433    cmp     r3, #0                      @ check object for null
7434    mov     r2, rINST, lsr #8           @ r2<- A(+)
7435    beq     common_errNullObject        @ object was null
7436    and     r2, r2, #15
7437    GET_VREG(r0, r2)                    @ r0<- fp[A]
7438    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7439    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7441    GOTO_OPCODE(ip)                     @ jump to next instruction
7442
7443
7444/* ------------------------------ */
7445    .balign 64
7446.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7447/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7448    /* iput-wide-quick vA, vB, offset@CCCC */
7449    mov     r0, rINST, lsr #8           @ r0<- A(+)
7450    mov     r1, rINST, lsr #12          @ r1<- B
7451    and     r0, r0, #15
7452    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7453    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7454    cmp     r2, #0                      @ check object for null
7455    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7456    beq     common_errNullObject        @ object was null
7457    FETCH(r3, 1)                        @ r3<- field byte offset
7458    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7459    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7460    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7461    GOTO_OPCODE(ip)                     @ jump to next instruction
7462
7463
7464/* ------------------------------ */
7465    .balign 64
7466.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7467/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7468/* File: armv5te/OP_IPUT_QUICK.S */
7469    /* For: iput-quick, iput-object-quick */
7470    /* op vA, vB, offset@CCCC */
7471    mov     r2, rINST, lsr #12          @ r2<- B
7472    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7473    FETCH(r1, 1)                        @ r1<- field byte offset
7474    cmp     r3, #0                      @ check object for null
7475    mov     r2, rINST, lsr #8           @ r2<- A(+)
7476    beq     common_errNullObject        @ object was null
7477    and     r2, r2, #15
7478    GET_VREG(r0, r2)                    @ r0<- fp[A]
7479    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7480    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7482    GOTO_OPCODE(ip)                     @ jump to next instruction
7483
7484
7485
7486/* ------------------------------ */
7487    .balign 64
7488.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7489/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7490    /*
7491     * Handle an optimized virtual method call.
7492     *
7493     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7494     */
7495    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7496    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7497    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7498    FETCH(r1, 1)                        @ r1<- BBBB
7499    .if     (!0)
7500    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7501    .endif
7502    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7503    cmp     r2, #0                      @ is "this" null?
7504    beq     common_errNullObject        @ null "this", throw exception
7505    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7506    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7507    EXPORT_PC()                         @ invoke must export
7508    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7509    bl      common_invokeMethodNoRange @ continue on
7510
7511/* ------------------------------ */
7512    .balign 64
7513.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7514/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7515/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7516    /*
7517     * Handle an optimized virtual method call.
7518     *
7519     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7520     */
7521    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7522    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7523    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7524    FETCH(r1, 1)                        @ r1<- BBBB
7525    .if     (!1)
7526    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7527    .endif
7528    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7529    cmp     r2, #0                      @ is "this" null?
7530    beq     common_errNullObject        @ null "this", throw exception
7531    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7532    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7533    EXPORT_PC()                         @ invoke must export
7534    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7535    bl      common_invokeMethodRange @ continue on
7536
7537
7538/* ------------------------------ */
7539    .balign 64
7540.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7541/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7542    /*
7543     * Handle an optimized "super" method call.
7544     *
7545     * for: [opt] invoke-super-quick, invoke-super-quick/range
7546     */
7547    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7548    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7549    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7550    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7551    .if     (!0)
7552    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7553    .endif
7554    FETCH(r1, 1)                        @ r1<- BBBB
7555    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7556    EXPORT_PC()                         @ must export for invoke
7557    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7558    GET_VREG(r3, r10)                   @ r3<- "this"
7559    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7560    cmp     r3, #0                      @ null "this" ref?
7561    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7562    beq     common_errNullObject        @ "this" is null, throw exception
7563    bl      common_invokeMethodNoRange @ continue on
7564
7565
7566/* ------------------------------ */
7567    .balign 64
7568.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7569/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7570/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7571    /*
7572     * Handle an optimized "super" method call.
7573     *
7574     * for: [opt] invoke-super-quick, invoke-super-quick/range
7575     */
7576    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7577    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7578    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7579    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7580    .if     (!1)
7581    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7582    .endif
7583    FETCH(r1, 1)                        @ r1<- BBBB
7584    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7585    EXPORT_PC()                         @ must export for invoke
7586    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7587    GET_VREG(r3, r10)                   @ r3<- "this"
7588    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7589    cmp     r3, #0                      @ null "this" ref?
7590    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7591    beq     common_errNullObject        @ "this" is null, throw exception
7592    bl      common_invokeMethodRange @ continue on
7593
7594
7595
7596/* ------------------------------ */
7597    .balign 64
7598.L_OP_UNUSED_FC: /* 0xfc */
7599/* File: armv5te/OP_UNUSED_FC.S */
7600/* File: armv5te/unused.S */
7601    bl      common_abort
7602
7603
7604
7605/* ------------------------------ */
7606    .balign 64
7607.L_OP_UNUSED_FD: /* 0xfd */
7608/* File: armv5te/OP_UNUSED_FD.S */
7609/* File: armv5te/unused.S */
7610    bl      common_abort
7611
7612
7613
7614/* ------------------------------ */
7615    .balign 64
7616.L_OP_UNUSED_FE: /* 0xfe */
7617/* File: armv5te/OP_UNUSED_FE.S */
7618/* File: armv5te/unused.S */
7619    bl      common_abort
7620
7621
7622
7623/* ------------------------------ */
7624    .balign 64
7625.L_OP_UNUSED_FF: /* 0xff */
7626/* File: armv5te/OP_UNUSED_FF.S */
7627/* File: armv5te/unused.S */
7628    bl      common_abort
7629
7630
7631
7632
7633    .balign 64
7634    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7635    .global dvmAsmInstructionEnd
7636dvmAsmInstructionEnd:
7637
7638/*
7639 * ===========================================================================
7640 *  Sister implementations
7641 * ===========================================================================
7642 */
7643    .global dvmAsmSisterStart
7644    .type   dvmAsmSisterStart, %function
7645    .text
7646    .balign 4
7647dvmAsmSisterStart:
7648
7649/* continuation for OP_CONST_STRING */
7650
7651    /*
7652     * Continuation if the String has not yet been resolved.
7653     *  r1: BBBB (String ref)
7654     *  r9: target register
7655     */
7656.LOP_CONST_STRING_resolve:
7657    EXPORT_PC()
7658    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7659    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7660    bl      dvmResolveString            @ r0<- String reference
7661    cmp     r0, #0                      @ failed?
7662    beq     common_exceptionThrown      @ yup, handle the exception
7663    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7664    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7665    SET_VREG(r0, r9)                    @ vAA<- r0
7666    GOTO_OPCODE(ip)                     @ jump to next instruction
7667
7668
7669/* continuation for OP_CONST_STRING_JUMBO */
7670
7671    /*
7672     * Continuation if the String has not yet been resolved.
7673     *  r1: BBBBBBBB (String ref)
7674     *  r9: target register
7675     */
7676.LOP_CONST_STRING_JUMBO_resolve:
7677    EXPORT_PC()
7678    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7679    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7680    bl      dvmResolveString            @ r0<- String reference
7681    cmp     r0, #0                      @ failed?
7682    beq     common_exceptionThrown      @ yup, handle the exception
7683    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7685    SET_VREG(r0, r9)                    @ vAA<- r0
7686    GOTO_OPCODE(ip)                     @ jump to next instruction
7687
7688
7689/* continuation for OP_CONST_CLASS */
7690
7691    /*
7692     * Continuation if the Class has not yet been resolved.
7693     *  r1: BBBB (Class ref)
7694     *  r9: target register
7695     */
7696.LOP_CONST_CLASS_resolve:
7697    EXPORT_PC()
7698    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7699    mov     r2, #1                      @ r2<- true
7700    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7701    bl      dvmResolveClass             @ r0<- Class reference
7702    cmp     r0, #0                      @ failed?
7703    beq     common_exceptionThrown      @ yup, handle the exception
7704    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7706    SET_VREG(r0, r9)                    @ vAA<- r0
7707    GOTO_OPCODE(ip)                     @ jump to next instruction
7708
7709
7710/* continuation for OP_CHECK_CAST */
7711
7712    /*
7713     * Trivial test failed, need to perform full check.  This is common.
7714     *  r0 holds obj->clazz
7715     *  r1 holds class resolved from BBBB
7716     *  r9 holds object
7717     */
7718.LOP_CHECK_CAST_fullcheck:
7719    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7720    cmp     r0, #0                      @ failed?
7721    bne     .LOP_CHECK_CAST_okay            @ no, success
7722
7723    @ A cast has failed.  We need to throw a ClassCastException with the
7724    @ class of the object that failed to be cast.
7725    EXPORT_PC()                         @ about to throw
7726    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7727    ldr     r0, .LstrClassCastExceptionPtr
7728    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7729    bl      dvmThrowExceptionWithClassMessage
7730    b       common_exceptionThrown
7731
7732    /*
7733     * Resolution required.  This is the least-likely path.
7734     *
7735     *  r2 holds BBBB
7736     *  r9 holds object
7737     */
7738.LOP_CHECK_CAST_resolve:
7739    EXPORT_PC()                         @ resolve() could throw
7740    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7741    mov     r1, r2                      @ r1<- BBBB
7742    mov     r2, #0                      @ r2<- false
7743    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7744    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7745    cmp     r0, #0                      @ got null?
7746    beq     common_exceptionThrown      @ yes, handle exception
7747    mov     r1, r0                      @ r1<- class resolved from BBB
7748    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7749    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7750
7751.LstrClassCastExceptionPtr:
7752    .word   .LstrClassCastException
7753
7754
7755/* continuation for OP_INSTANCE_OF */
7756
7757    /*
7758     * Trivial test failed, need to perform full check.  This is common.
7759     *  r0 holds obj->clazz
7760     *  r1 holds class resolved from BBBB
7761     *  r9 holds A
7762     */
7763.LOP_INSTANCE_OF_fullcheck:
7764    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7765    @ fall through to OP_INSTANCE_OF_store
7766
7767    /*
7768     * r0 holds boolean result
7769     * r9 holds A
7770     */
7771.LOP_INSTANCE_OF_store:
7772    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7773    SET_VREG(r0, r9)                    @ vA<- r0
7774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7775    GOTO_OPCODE(ip)                     @ jump to next instruction
7776
7777    /*
7778     * Trivial test succeeded, save and bail.
7779     *  r9 holds A
7780     */
7781.LOP_INSTANCE_OF_trivial:
7782    mov     r0, #1                      @ indicate success
7783    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7784    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7785    SET_VREG(r0, r9)                    @ vA<- r0
7786    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7787    GOTO_OPCODE(ip)                     @ jump to next instruction
7788
7789    /*
7790     * Resolution required.  This is the least-likely path.
7791     *
7792     *  r3 holds BBBB
7793     *  r9 holds A
7794     */
7795.LOP_INSTANCE_OF_resolve:
7796    EXPORT_PC()                         @ resolve() could throw
7797    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7798    mov     r1, r3                      @ r1<- BBBB
7799    mov     r2, #1                      @ r2<- true
7800    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7801    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7802    cmp     r0, #0                      @ got null?
7803    beq     common_exceptionThrown      @ yes, handle exception
7804    mov     r1, r0                      @ r1<- class resolved from BBB
7805    mov     r3, rINST, lsr #12          @ r3<- B
7806    GET_VREG(r0, r3)                    @ r0<- vB (object)
7807    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7808    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7809
7810
7811/* continuation for OP_NEW_INSTANCE */
7812
7813    .balign 32                          @ minimize cache lines
7814.LOP_NEW_INSTANCE_finish: @ r0=new object
7815    mov     r3, rINST, lsr #8           @ r3<- AA
7816    cmp     r0, #0                      @ failed?
7817    beq     common_exceptionThrown      @ yes, handle the exception
7818    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7819    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7820    SET_VREG(r0, r3)                    @ vAA<- r0
7821    GOTO_OPCODE(ip)                     @ jump to next instruction
7822
7823    /*
7824     * Class initialization required.
7825     *
7826     *  r0 holds class object
7827     */
7828.LOP_NEW_INSTANCE_needinit:
7829    mov     r9, r0                      @ save r0
7830    bl      dvmInitClass                @ initialize class
7831    cmp     r0, #0                      @ check boolean result
7832    mov     r0, r9                      @ restore r0
7833    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7834    b       common_exceptionThrown      @ failed, deal with init exception
7835
7836    /*
7837     * Resolution required.  This is the least-likely path.
7838     *
7839     *  r1 holds BBBB
7840     */
7841.LOP_NEW_INSTANCE_resolve:
7842    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7843    mov     r2, #0                      @ r2<- false
7844    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7845    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7846    cmp     r0, #0                      @ got null?
7847    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7848    b       common_exceptionThrown      @ yes, handle exception
7849
7850.LstrInstantiationErrorPtr:
7851    .word   .LstrInstantiationError
7852
7853
7854/* continuation for OP_NEW_ARRAY */
7855
7856
7857    /*
7858     * Resolve class.  (This is an uncommon case.)
7859     *
7860     *  r1 holds array length
7861     *  r2 holds class ref CCCC
7862     */
7863.LOP_NEW_ARRAY_resolve:
7864    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7865    mov     r9, r1                      @ r9<- length (save)
7866    mov     r1, r2                      @ r1<- CCCC
7867    mov     r2, #0                      @ r2<- false
7868    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7869    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7870    cmp     r0, #0                      @ got null?
7871    mov     r1, r9                      @ r1<- length (restore)
7872    beq     common_exceptionThrown      @ yes, handle exception
7873    @ fall through to OP_NEW_ARRAY_finish
7874
7875    /*
7876     * Finish allocation.
7877     *
7878     *  r0 holds class
7879     *  r1 holds array length
7880     */
7881.LOP_NEW_ARRAY_finish:
7882    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7883    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7884    cmp     r0, #0                      @ failed?
7885    mov     r2, rINST, lsr #8           @ r2<- A+
7886    beq     common_exceptionThrown      @ yes, handle the exception
7887    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7888    and     r2, r2, #15                 @ r2<- A
7889    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7890    SET_VREG(r0, r2)                    @ vA<- r0
7891    GOTO_OPCODE(ip)                     @ jump to next instruction
7892
7893
7894/* continuation for OP_FILLED_NEW_ARRAY */
7895
7896    /*
7897     * On entry:
7898     *  r0 holds array class
7899     *  r10 holds AA or BA
7900     */
7901.LOP_FILLED_NEW_ARRAY_continue:
7902    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7903    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7904    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7905    .if     0
7906    mov     r1, r10                     @ r1<- AA (length)
7907    .else
7908    mov     r1, r10, lsr #4             @ r1<- B (length)
7909    .endif
7910    cmp     r3, #'I'                    @ array of ints?
7911    cmpne   r3, #'L'                    @ array of objects?
7912    cmpne   r3, #'['                    @ array of arrays?
7913    mov     r9, r1                      @ save length in r9
7914    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7915    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7916    cmp     r0, #0                      @ null return?
7917    beq     common_exceptionThrown      @ alloc failed, handle exception
7918
7919    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7920    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7921    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7922    subs    r9, r9, #1                  @ length--, check for neg
7923    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7924    bmi     2f                          @ was zero, bail
7925
7926    @ copy values from registers into the array
7927    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7928    .if     0
7929    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79301:  ldr     r3, [r2], #4                @ r3<- *r2++
7931    subs    r9, r9, #1                  @ count--
7932    str     r3, [r0], #4                @ *contents++ = vX
7933    bpl     1b
7934    @ continue at 2
7935    .else
7936    cmp     r9, #4                      @ length was initially 5?
7937    and     r2, r10, #15                @ r2<- A
7938    bne     1f                          @ <= 4 args, branch
7939    GET_VREG(r3, r2)                    @ r3<- vA
7940    sub     r9, r9, #1                  @ count--
7941    str     r3, [r0, #16]               @ contents[4] = vA
79421:  and     r2, r1, #15                 @ r2<- F/E/D/C
7943    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7944    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7945    subs    r9, r9, #1                  @ count--
7946    str     r3, [r0], #4                @ *contents++ = vX
7947    bpl     1b
7948    @ continue at 2
7949    .endif
7950
79512:
7952    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7953    GOTO_OPCODE(ip)                     @ execute it
7954
7955    /*
7956     * Throw an exception indicating that we have not implemented this
7957     * mode of filled-new-array.
7958     */
7959.LOP_FILLED_NEW_ARRAY_notimpl:
7960    ldr     r0, .L_strInternalError
7961    ldr     r1, .L_strFilledNewArrayNotImpl
7962    bl      dvmThrowException
7963    b       common_exceptionThrown
7964
7965    .if     (!0)                 @ define in one or the other, not both
7966.L_strFilledNewArrayNotImpl:
7967    .word   .LstrFilledNewArrayNotImpl
7968.L_strInternalError:
7969    .word   .LstrInternalError
7970    .endif
7971
7972
7973/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7974
7975    /*
7976     * On entry:
7977     *  r0 holds array class
7978     *  r10 holds AA or BA
7979     */
7980.LOP_FILLED_NEW_ARRAY_RANGE_continue:
7981    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7982    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7983    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7984    .if     1
7985    mov     r1, r10                     @ r1<- AA (length)
7986    .else
7987    mov     r1, r10, lsr #4             @ r1<- B (length)
7988    .endif
7989    cmp     r3, #'I'                    @ array of ints?
7990    cmpne   r3, #'L'                    @ array of objects?
7991    cmpne   r3, #'['                    @ array of arrays?
7992    mov     r9, r1                      @ save length in r9
7993    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7994    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7995    cmp     r0, #0                      @ null return?
7996    beq     common_exceptionThrown      @ alloc failed, handle exception
7997
7998    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7999    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8000    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8001    subs    r9, r9, #1                  @ length--, check for neg
8002    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8003    bmi     2f                          @ was zero, bail
8004
8005    @ copy values from registers into the array
8006    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8007    .if     1
8008    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80091:  ldr     r3, [r2], #4                @ r3<- *r2++
8010    subs    r9, r9, #1                  @ count--
8011    str     r3, [r0], #4                @ *contents++ = vX
8012    bpl     1b
8013    @ continue at 2
8014    .else
8015    cmp     r9, #4                      @ length was initially 5?
8016    and     r2, r10, #15                @ r2<- A
8017    bne     1f                          @ <= 4 args, branch
8018    GET_VREG(r3, r2)                    @ r3<- vA
8019    sub     r9, r9, #1                  @ count--
8020    str     r3, [r0, #16]               @ contents[4] = vA
80211:  and     r2, r1, #15                 @ r2<- F/E/D/C
8022    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8023    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8024    subs    r9, r9, #1                  @ count--
8025    str     r3, [r0], #4                @ *contents++ = vX
8026    bpl     1b
8027    @ continue at 2
8028    .endif
8029
80302:
8031    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8032    GOTO_OPCODE(ip)                     @ execute it
8033
8034    /*
8035     * Throw an exception indicating that we have not implemented this
8036     * mode of filled-new-array.
8037     */
8038.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8039    ldr     r0, .L_strInternalError
8040    ldr     r1, .L_strFilledNewArrayNotImpl
8041    bl      dvmThrowException
8042    b       common_exceptionThrown
8043
8044    .if     (!1)                 @ define in one or the other, not both
8045.L_strFilledNewArrayNotImpl:
8046    .word   .LstrFilledNewArrayNotImpl
8047.L_strInternalError:
8048    .word   .LstrInternalError
8049    .endif
8050
8051
8052/* continuation for OP_CMPL_FLOAT */
8053.LOP_CMPL_FLOAT_finish:
8054    SET_VREG(r0, r9)                    @ vAA<- r0
8055    GOTO_OPCODE(ip)                     @ jump to next instruction
8056
8057
8058/* continuation for OP_CMPG_FLOAT */
8059.LOP_CMPG_FLOAT_finish:
8060    SET_VREG(r0, r9)                    @ vAA<- r0
8061    GOTO_OPCODE(ip)                     @ jump to next instruction
8062
8063
8064/* continuation for OP_CMPL_DOUBLE */
8065.LOP_CMPL_DOUBLE_finish:
8066    SET_VREG(r0, r9)                    @ vAA<- r0
8067    GOTO_OPCODE(ip)                     @ jump to next instruction
8068
8069
8070/* continuation for OP_CMPG_DOUBLE */
8071.LOP_CMPG_DOUBLE_finish:
8072    SET_VREG(r0, r9)                    @ vAA<- r0
8073    GOTO_OPCODE(ip)                     @ jump to next instruction
8074
8075
8076/* continuation for OP_CMP_LONG */
8077
8078.LOP_CMP_LONG_less:
8079    mvn     r1, #0                      @ r1<- -1
8080    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8081    @ instead, we just replicate the tail end.
8082    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8083    SET_VREG(r1, r9)                    @ vAA<- r1
8084    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8085    GOTO_OPCODE(ip)                     @ jump to next instruction
8086
8087.LOP_CMP_LONG_greater:
8088    mov     r1, #1                      @ r1<- 1
8089    @ fall through to _finish
8090
8091.LOP_CMP_LONG_finish:
8092    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8093    SET_VREG(r1, r9)                    @ vAA<- r1
8094    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8095    GOTO_OPCODE(ip)                     @ jump to next instruction
8096
8097
8098/* continuation for OP_AGET_WIDE */
8099
8100.LOP_AGET_WIDE_finish:
8101    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8102    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8103    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8105    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8106    GOTO_OPCODE(ip)                     @ jump to next instruction
8107
8108
8109/* continuation for OP_APUT_WIDE */
8110
8111.LOP_APUT_WIDE_finish:
8112    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8113    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8115    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8116    GOTO_OPCODE(ip)                     @ jump to next instruction
8117
8118
8119/* continuation for OP_APUT_OBJECT */
8120    /*
8121     * On entry:
8122     *  r1 = vBB (arrayObj)
8123     *  r9 = vAA (obj)
8124     *  r10 = offset into array (vBB + vCC * width)
8125     */
8126.LOP_APUT_OBJECT_finish:
8127    cmp     r9, #0                      @ storing null reference?
8128    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8129    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8130    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8131    bl      dvmCanPutArrayElement       @ test object type vs. array type
8132    cmp     r0, #0                      @ okay?
8133    beq     common_errArrayStore        @ no
8134.LOP_APUT_OBJECT_skip_check:
8135    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8136    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8137    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8138    GOTO_OPCODE(ip)                     @ jump to next instruction
8139
8140
8141/* continuation for OP_IGET */
8142
8143    /*
8144     * Currently:
8145     *  r0 holds resolved field
8146     *  r9 holds object
8147     */
8148.LOP_IGET_finish:
8149    @bl      common_squeak0
8150    cmp     r9, #0                      @ check object for null
8151    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8152    beq     common_errNullObject        @ object was null
8153    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8154    mov     r2, rINST, lsr #8           @ r2<- A+
8155    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8156    and     r2, r2, #15                 @ r2<- A
8157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8158    SET_VREG(r0, r2)                    @ fp[A]<- r0
8159    GOTO_OPCODE(ip)                     @ jump to next instruction
8160
8161
8162/* continuation for OP_IGET_WIDE */
8163
8164    /*
8165     * Currently:
8166     *  r0 holds resolved field
8167     *  r9 holds object
8168     */
8169.LOP_IGET_WIDE_finish:
8170    cmp     r9, #0                      @ check object for null
8171    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8172    beq     common_errNullObject        @ object was null
8173    mov     r2, rINST, lsr #8           @ r2<- A+
8174    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8175    and     r2, r2, #15                 @ r2<- A
8176    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8177    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8179    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8180    GOTO_OPCODE(ip)                     @ jump to next instruction
8181
8182
8183/* continuation for OP_IGET_OBJECT */
8184
8185    /*
8186     * Currently:
8187     *  r0 holds resolved field
8188     *  r9 holds object
8189     */
8190.LOP_IGET_OBJECT_finish:
8191    @bl      common_squeak0
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    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8196    mov     r2, rINST, lsr #8           @ r2<- A+
8197    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8198    and     r2, r2, #15                 @ r2<- A
8199    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8200    SET_VREG(r0, r2)                    @ fp[A]<- r0
8201    GOTO_OPCODE(ip)                     @ jump to next instruction
8202
8203
8204/* continuation for OP_IGET_BOOLEAN */
8205
8206    /*
8207     * Currently:
8208     *  r0 holds resolved field
8209     *  r9 holds object
8210     */
8211.LOP_IGET_BOOLEAN_finish:
8212    @bl      common_squeak1
8213    cmp     r9, #0                      @ check object for null
8214    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8215    beq     common_errNullObject        @ object was null
8216    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8217    mov     r2, rINST, lsr #8           @ r2<- A+
8218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8219    and     r2, r2, #15                 @ r2<- A
8220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8221    SET_VREG(r0, r2)                    @ fp[A]<- r0
8222    GOTO_OPCODE(ip)                     @ jump to next instruction
8223
8224
8225/* continuation for OP_IGET_BYTE */
8226
8227    /*
8228     * Currently:
8229     *  r0 holds resolved field
8230     *  r9 holds object
8231     */
8232.LOP_IGET_BYTE_finish:
8233    @bl      common_squeak2
8234    cmp     r9, #0                      @ check object for null
8235    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8236    beq     common_errNullObject        @ object was null
8237    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8238    mov     r2, rINST, lsr #8           @ r2<- A+
8239    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8240    and     r2, r2, #15                 @ r2<- A
8241    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8242    SET_VREG(r0, r2)                    @ fp[A]<- r0
8243    GOTO_OPCODE(ip)                     @ jump to next instruction
8244
8245
8246/* continuation for OP_IGET_CHAR */
8247
8248    /*
8249     * Currently:
8250     *  r0 holds resolved field
8251     *  r9 holds object
8252     */
8253.LOP_IGET_CHAR_finish:
8254    @bl      common_squeak3
8255    cmp     r9, #0                      @ check object for null
8256    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8257    beq     common_errNullObject        @ object was null
8258    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8259    mov     r2, rINST, lsr #8           @ r2<- A+
8260    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8261    and     r2, r2, #15                 @ r2<- A
8262    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8263    SET_VREG(r0, r2)                    @ fp[A]<- r0
8264    GOTO_OPCODE(ip)                     @ jump to next instruction
8265
8266
8267/* continuation for OP_IGET_SHORT */
8268
8269    /*
8270     * Currently:
8271     *  r0 holds resolved field
8272     *  r9 holds object
8273     */
8274.LOP_IGET_SHORT_finish:
8275    @bl      common_squeak4
8276    cmp     r9, #0                      @ check object for null
8277    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8278    beq     common_errNullObject        @ object was null
8279    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8280    mov     r2, rINST, lsr #8           @ r2<- A+
8281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8282    and     r2, r2, #15                 @ r2<- A
8283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8284    SET_VREG(r0, r2)                    @ fp[A]<- r0
8285    GOTO_OPCODE(ip)                     @ jump to next instruction
8286
8287
8288/* continuation for OP_IPUT */
8289
8290    /*
8291     * Currently:
8292     *  r0 holds resolved field
8293     *  r9 holds object
8294     */
8295.LOP_IPUT_finish:
8296    @bl      common_squeak0
8297    mov     r1, rINST, lsr #8           @ r1<- A+
8298    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8299    and     r1, r1, #15                 @ r1<- A
8300    cmp     r9, #0                      @ check object for null
8301    GET_VREG(r0, r1)                    @ r0<- fp[A]
8302    beq     common_errNullObject        @ object was null
8303    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8305    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8306    GOTO_OPCODE(ip)                     @ jump to next instruction
8307
8308
8309/* continuation for OP_IPUT_WIDE */
8310
8311    /*
8312     * Currently:
8313     *  r0 holds resolved field
8314     *  r9 holds object
8315     */
8316.LOP_IPUT_WIDE_finish:
8317    mov     r2, rINST, lsr #8           @ r2<- A+
8318    cmp     r9, #0                      @ check object for null
8319    and     r2, r2, #15                 @ r2<- A
8320    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8321    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8322    beq     common_errNullObject        @ object was null
8323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8324    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8326    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8327    GOTO_OPCODE(ip)                     @ jump to next instruction
8328
8329
8330/* continuation for OP_IPUT_OBJECT */
8331
8332    /*
8333     * Currently:
8334     *  r0 holds resolved field
8335     *  r9 holds object
8336     */
8337.LOP_IPUT_OBJECT_finish:
8338    @bl      common_squeak0
8339    mov     r1, rINST, lsr #8           @ r1<- A+
8340    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8341    and     r1, r1, #15                 @ r1<- A
8342    cmp     r9, #0                      @ check object for null
8343    GET_VREG(r0, r1)                    @ r0<- fp[A]
8344    beq     common_errNullObject        @ object was null
8345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8347    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8348    GOTO_OPCODE(ip)                     @ jump to next instruction
8349
8350
8351/* continuation for OP_IPUT_BOOLEAN */
8352
8353    /*
8354     * Currently:
8355     *  r0 holds resolved field
8356     *  r9 holds object
8357     */
8358.LOP_IPUT_BOOLEAN_finish:
8359    @bl      common_squeak1
8360    mov     r1, rINST, lsr #8           @ r1<- A+
8361    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8362    and     r1, r1, #15                 @ r1<- A
8363    cmp     r9, #0                      @ check object for null
8364    GET_VREG(r0, r1)                    @ r0<- fp[A]
8365    beq     common_errNullObject        @ object was null
8366    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8368    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8369    GOTO_OPCODE(ip)                     @ jump to next instruction
8370
8371
8372/* continuation for OP_IPUT_BYTE */
8373
8374    /*
8375     * Currently:
8376     *  r0 holds resolved field
8377     *  r9 holds object
8378     */
8379.LOP_IPUT_BYTE_finish:
8380    @bl      common_squeak2
8381    mov     r1, rINST, lsr #8           @ r1<- A+
8382    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8383    and     r1, r1, #15                 @ r1<- A
8384    cmp     r9, #0                      @ check object for null
8385    GET_VREG(r0, r1)                    @ r0<- fp[A]
8386    beq     common_errNullObject        @ object was null
8387    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8389    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8390    GOTO_OPCODE(ip)                     @ jump to next instruction
8391
8392
8393/* continuation for OP_IPUT_CHAR */
8394
8395    /*
8396     * Currently:
8397     *  r0 holds resolved field
8398     *  r9 holds object
8399     */
8400.LOP_IPUT_CHAR_finish:
8401    @bl      common_squeak3
8402    mov     r1, rINST, lsr #8           @ r1<- A+
8403    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8404    and     r1, r1, #15                 @ r1<- A
8405    cmp     r9, #0                      @ check object for null
8406    GET_VREG(r0, r1)                    @ r0<- fp[A]
8407    beq     common_errNullObject        @ object was null
8408    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8409    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8410    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8411    GOTO_OPCODE(ip)                     @ jump to next instruction
8412
8413
8414/* continuation for OP_IPUT_SHORT */
8415
8416    /*
8417     * Currently:
8418     *  r0 holds resolved field
8419     *  r9 holds object
8420     */
8421.LOP_IPUT_SHORT_finish:
8422    @bl      common_squeak4
8423    mov     r1, rINST, lsr #8           @ r1<- A+
8424    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8425    and     r1, r1, #15                 @ r1<- A
8426    cmp     r9, #0                      @ check object for null
8427    GET_VREG(r0, r1)                    @ r0<- fp[A]
8428    beq     common_errNullObject        @ object was null
8429    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8430    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8431    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8432    GOTO_OPCODE(ip)                     @ jump to next instruction
8433
8434
8435/* continuation for OP_SGET */
8436
8437    /*
8438     * Continuation if the field has not yet been resolved.
8439     *  r1: BBBB field ref
8440     */
8441.LOP_SGET_resolve:
8442    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8443    EXPORT_PC()                         @ resolve() could throw, so export now
8444    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8445    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8446    cmp     r0, #0                      @ success?
8447    bne     .LOP_SGET_finish          @ yes, finish
8448    b       common_exceptionThrown      @ no, handle exception
8449
8450
8451/* continuation for OP_SGET_WIDE */
8452
8453    /*
8454     * Continuation if the field has not yet been resolved.
8455     *  r1: BBBB field ref
8456     */
8457.LOP_SGET_WIDE_resolve:
8458    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8459    EXPORT_PC()                         @ resolve() could throw, so export now
8460    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8461    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8462    cmp     r0, #0                      @ success?
8463    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8464    b       common_exceptionThrown      @ no, handle exception
8465
8466
8467/* continuation for OP_SGET_OBJECT */
8468
8469    /*
8470     * Continuation if the field has not yet been resolved.
8471     *  r1: BBBB field ref
8472     */
8473.LOP_SGET_OBJECT_resolve:
8474    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8475    EXPORT_PC()                         @ resolve() could throw, so export now
8476    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8477    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8478    cmp     r0, #0                      @ success?
8479    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8480    b       common_exceptionThrown      @ no, handle exception
8481
8482
8483/* continuation for OP_SGET_BOOLEAN */
8484
8485    /*
8486     * Continuation if the field has not yet been resolved.
8487     *  r1: BBBB field ref
8488     */
8489.LOP_SGET_BOOLEAN_resolve:
8490    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8491    EXPORT_PC()                         @ resolve() could throw, so export now
8492    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8493    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8494    cmp     r0, #0                      @ success?
8495    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8496    b       common_exceptionThrown      @ no, handle exception
8497
8498
8499/* continuation for OP_SGET_BYTE */
8500
8501    /*
8502     * Continuation if the field has not yet been resolved.
8503     *  r1: BBBB field ref
8504     */
8505.LOP_SGET_BYTE_resolve:
8506    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8507    EXPORT_PC()                         @ resolve() could throw, so export now
8508    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8509    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8510    cmp     r0, #0                      @ success?
8511    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8512    b       common_exceptionThrown      @ no, handle exception
8513
8514
8515/* continuation for OP_SGET_CHAR */
8516
8517    /*
8518     * Continuation if the field has not yet been resolved.
8519     *  r1: BBBB field ref
8520     */
8521.LOP_SGET_CHAR_resolve:
8522    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8523    EXPORT_PC()                         @ resolve() could throw, so export now
8524    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8525    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8526    cmp     r0, #0                      @ success?
8527    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8528    b       common_exceptionThrown      @ no, handle exception
8529
8530
8531/* continuation for OP_SGET_SHORT */
8532
8533    /*
8534     * Continuation if the field has not yet been resolved.
8535     *  r1: BBBB field ref
8536     */
8537.LOP_SGET_SHORT_resolve:
8538    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8539    EXPORT_PC()                         @ resolve() could throw, so export now
8540    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8541    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8542    cmp     r0, #0                      @ success?
8543    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8544    b       common_exceptionThrown      @ no, handle exception
8545
8546
8547/* continuation for OP_SPUT */
8548
8549    /*
8550     * Continuation if the field has not yet been resolved.
8551     *  r1: BBBB field ref
8552     */
8553.LOP_SPUT_resolve:
8554    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8555    EXPORT_PC()                         @ resolve() could throw, so export now
8556    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8557    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8558    cmp     r0, #0                      @ success?
8559    bne     .LOP_SPUT_finish          @ yes, finish
8560    b       common_exceptionThrown      @ no, handle exception
8561
8562
8563/* continuation for OP_SPUT_WIDE */
8564
8565    /*
8566     * Continuation if the field has not yet been resolved.
8567     *  r1: BBBB field ref
8568     *  r9: &fp[AA]
8569     */
8570.LOP_SPUT_WIDE_resolve:
8571    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8572    EXPORT_PC()                         @ resolve() could throw, so export now
8573    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8574    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8575    cmp     r0, #0                      @ success?
8576    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8577    b       common_exceptionThrown      @ no, handle exception
8578
8579
8580/* continuation for OP_SPUT_OBJECT */
8581
8582    /*
8583     * Continuation if the field has not yet been resolved.
8584     *  r1: BBBB field ref
8585     */
8586.LOP_SPUT_OBJECT_resolve:
8587    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8588    EXPORT_PC()                         @ resolve() could throw, so export now
8589    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8590    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8591    cmp     r0, #0                      @ success?
8592    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8593    b       common_exceptionThrown      @ no, handle exception
8594
8595
8596/* continuation for OP_SPUT_BOOLEAN */
8597
8598    /*
8599     * Continuation if the field has not yet been resolved.
8600     *  r1: BBBB field ref
8601     */
8602.LOP_SPUT_BOOLEAN_resolve:
8603    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8604    EXPORT_PC()                         @ resolve() could throw, so export now
8605    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8606    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8607    cmp     r0, #0                      @ success?
8608    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8609    b       common_exceptionThrown      @ no, handle exception
8610
8611
8612/* continuation for OP_SPUT_BYTE */
8613
8614    /*
8615     * Continuation if the field has not yet been resolved.
8616     *  r1: BBBB field ref
8617     */
8618.LOP_SPUT_BYTE_resolve:
8619    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8620    EXPORT_PC()                         @ resolve() could throw, so export now
8621    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8622    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8623    cmp     r0, #0                      @ success?
8624    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8625    b       common_exceptionThrown      @ no, handle exception
8626
8627
8628/* continuation for OP_SPUT_CHAR */
8629
8630    /*
8631     * Continuation if the field has not yet been resolved.
8632     *  r1: BBBB field ref
8633     */
8634.LOP_SPUT_CHAR_resolve:
8635    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8636    EXPORT_PC()                         @ resolve() could throw, so export now
8637    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8638    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8639    cmp     r0, #0                      @ success?
8640    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8641    b       common_exceptionThrown      @ no, handle exception
8642
8643
8644/* continuation for OP_SPUT_SHORT */
8645
8646    /*
8647     * Continuation if the field has not yet been resolved.
8648     *  r1: BBBB field ref
8649     */
8650.LOP_SPUT_SHORT_resolve:
8651    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8652    EXPORT_PC()                         @ resolve() could throw, so export now
8653    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8654    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8655    cmp     r0, #0                      @ success?
8656    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8657    b       common_exceptionThrown      @ no, handle exception
8658
8659
8660/* continuation for OP_INVOKE_VIRTUAL */
8661
8662    /*
8663     * At this point:
8664     *  r0 = resolved base method
8665     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8666     */
8667.LOP_INVOKE_VIRTUAL_continue:
8668    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8669    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8670    cmp     r1, #0                      @ is "this" null?
8671    beq     common_errNullObject        @ null "this", throw exception
8672    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8673    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8674    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8675    bl      common_invokeMethodNoRange @ continue on
8676
8677
8678/* continuation for OP_INVOKE_SUPER */
8679
8680    /*
8681     * At this point:
8682     *  r0 = resolved base method
8683     *  r9 = method->clazz
8684     */
8685.LOP_INVOKE_SUPER_continue:
8686    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8687    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8688    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8689    EXPORT_PC()                         @ must export for invoke
8690    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8691    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8692    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8693    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8694    bl      common_invokeMethodNoRange @ continue on
8695
8696.LOP_INVOKE_SUPER_resolve:
8697    mov     r0, r9                      @ r0<- method->clazz
8698    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8699    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8700    cmp     r0, #0                      @ got null?
8701    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8702    b       common_exceptionThrown      @ yes, handle exception
8703
8704    /*
8705     * Throw a NoSuchMethodError with the method name as the message.
8706     *  r0 = resolved base method
8707     */
8708.LOP_INVOKE_SUPER_nsm:
8709    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8710    b       common_errNoSuchMethod
8711
8712
8713/* continuation for OP_INVOKE_DIRECT */
8714
8715    /*
8716     * On entry:
8717     *  r1 = reference (BBBB or CCCC)
8718     *  r10 = "this" register
8719     */
8720.LOP_INVOKE_DIRECT_resolve:
8721    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8722    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8723    mov     r2, #METHOD_DIRECT          @ resolver method type
8724    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8725    cmp     r0, #0                      @ got null?
8726    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8727    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8728    b       common_exceptionThrown      @ yes, handle exception
8729
8730
8731/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8732
8733    /*
8734     * At this point:
8735     *  r0 = resolved base method
8736     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8737     */
8738.LOP_INVOKE_VIRTUAL_RANGE_continue:
8739    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8740    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8741    cmp     r1, #0                      @ is "this" null?
8742    beq     common_errNullObject        @ null "this", throw exception
8743    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8744    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8745    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8746    bl      common_invokeMethodRange @ continue on
8747
8748
8749/* continuation for OP_INVOKE_SUPER_RANGE */
8750
8751    /*
8752     * At this point:
8753     *  r0 = resolved base method
8754     *  r9 = method->clazz
8755     */
8756.LOP_INVOKE_SUPER_RANGE_continue:
8757    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8758    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8759    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8760    EXPORT_PC()                         @ must export for invoke
8761    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8762    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8763    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8764    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8765    bl      common_invokeMethodRange @ continue on
8766
8767.LOP_INVOKE_SUPER_RANGE_resolve:
8768    mov     r0, r9                      @ r0<- method->clazz
8769    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8770    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8771    cmp     r0, #0                      @ got null?
8772    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8773    b       common_exceptionThrown      @ yes, handle exception
8774
8775    /*
8776     * Throw a NoSuchMethodError with the method name as the message.
8777     *  r0 = resolved base method
8778     */
8779.LOP_INVOKE_SUPER_RANGE_nsm:
8780    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8781    b       common_errNoSuchMethod
8782
8783
8784/* continuation for OP_INVOKE_DIRECT_RANGE */
8785
8786    /*
8787     * On entry:
8788     *  r1 = reference (BBBB or CCCC)
8789     *  r10 = "this" register
8790     */
8791.LOP_INVOKE_DIRECT_RANGE_resolve:
8792    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8793    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8794    mov     r2, #METHOD_DIRECT          @ resolver method type
8795    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8796    cmp     r0, #0                      @ got null?
8797    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8798    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8799    b       common_exceptionThrown      @ yes, handle exception
8800
8801
8802/* continuation for OP_FLOAT_TO_LONG */
8803/*
8804 * Convert the float in r0 to a long in r0/r1.
8805 *
8806 * We have to clip values to long min/max per the specification.  The
8807 * expected common case is a "reasonable" value that converts directly
8808 * to modest integer.  The EABI convert function isn't doing this for us.
8809 */
8810f2l_doconv:
8811    stmfd   sp!, {r4, lr}
8812    mov     r1, #0x5f000000             @ (float)maxlong
8813    mov     r4, r0
8814    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8815    cmp     r0, #0                      @ nonzero == yes
8816    mvnne   r0, #0                      @ return maxlong (7fffffff)
8817    mvnne   r1, #0x80000000
8818    ldmnefd sp!, {r4, pc}
8819
8820    mov     r0, r4                      @ recover arg
8821    mov     r1, #0xdf000000             @ (float)minlong
8822    bl      __aeabi_fcmple              @ is arg <= minlong?
8823    cmp     r0, #0                      @ nonzero == yes
8824    movne   r0, #0                      @ return minlong (80000000)
8825    movne   r1, #0x80000000
8826    ldmnefd sp!, {r4, pc}
8827
8828    mov     r0, r4                      @ recover arg
8829    mov     r1, r4
8830    bl      __aeabi_fcmpeq              @ is arg == self?
8831    cmp     r0, #0                      @ zero == no
8832    moveq   r1, #0                      @ return zero for NaN
8833    ldmeqfd sp!, {r4, pc}
8834
8835    mov     r0, r4                      @ recover arg
8836    bl      __aeabi_f2lz                @ convert float to long
8837    ldmfd   sp!, {r4, pc}
8838
8839
8840/* continuation for OP_DOUBLE_TO_LONG */
8841/*
8842 * Convert the double in r0/r1 to a long in r0/r1.
8843 *
8844 * We have to clip values to long min/max per the specification.  The
8845 * expected common case is a "reasonable" value that converts directly
8846 * to modest integer.  The EABI convert function isn't doing this for us.
8847 */
8848d2l_doconv:
8849    stmfd   sp!, {r4, r5, lr}           @ save regs
8850    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8851    add     r3, #0x00e00000             @  0x43e00000
8852    mov     r2, #0                      @ maxlong, as a double (low word)
8853    sub     sp, sp, #4                  @ align for EABI
8854    mov     r4, r0                      @ save a copy of r0
8855    mov     r5, r1                      @  and r1
8856    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8857    cmp     r0, #0                      @ nonzero == yes
8858    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8859    mvnne   r1, #0x80000000
8860    bne     1f
8861
8862    mov     r0, r4                      @ recover arg
8863    mov     r1, r5
8864    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8865    add     r3, #0x00e00000             @  0xc3e00000
8866    mov     r2, #0                      @ minlong, as a double (low word)
8867    bl      __aeabi_dcmple              @ is arg <= minlong?
8868    cmp     r0, #0                      @ nonzero == yes
8869    movne   r0, #0                      @ return minlong (8000000000000000)
8870    movne   r1, #0x80000000
8871    bne     1f
8872
8873    mov     r0, r4                      @ recover arg
8874    mov     r1, r5
8875    mov     r2, r4                      @ compare against self
8876    mov     r3, r5
8877    bl      __aeabi_dcmpeq              @ is arg == self?
8878    cmp     r0, #0                      @ zero == no
8879    moveq   r1, #0                      @ return zero for NaN
8880    beq     1f
8881
8882    mov     r0, r4                      @ recover arg
8883    mov     r1, r5
8884    bl      __aeabi_d2lz                @ convert double to long
8885
88861:
8887    add     sp, sp, #4
8888    ldmfd   sp!, {r4, r5, pc}
8889
8890
8891/* continuation for OP_MUL_LONG */
8892
8893.LOP_MUL_LONG_finish:
8894    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8895    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8896    GOTO_OPCODE(ip)                     @ jump to next instruction
8897
8898
8899/* continuation for OP_SHL_LONG */
8900
8901.LOP_SHL_LONG_finish:
8902    mov     r0, r0, asl r2              @  r0<- r0 << r2
8903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8904    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8905    GOTO_OPCODE(ip)                     @ jump to next instruction
8906
8907
8908/* continuation for OP_SHR_LONG */
8909
8910.LOP_SHR_LONG_finish:
8911    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8913    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8914    GOTO_OPCODE(ip)                     @ jump to next instruction
8915
8916
8917/* continuation for OP_USHR_LONG */
8918
8919.LOP_USHR_LONG_finish:
8920    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8921    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8922    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8923    GOTO_OPCODE(ip)                     @ jump to next instruction
8924
8925
8926/* continuation for OP_SHL_LONG_2ADDR */
8927
8928.LOP_SHL_LONG_2ADDR_finish:
8929    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8930    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8931    GOTO_OPCODE(ip)                     @ jump to next instruction
8932
8933
8934/* continuation for OP_SHR_LONG_2ADDR */
8935
8936.LOP_SHR_LONG_2ADDR_finish:
8937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8938    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8939    GOTO_OPCODE(ip)                     @ jump to next instruction
8940
8941
8942/* continuation for OP_USHR_LONG_2ADDR */
8943
8944.LOP_USHR_LONG_2ADDR_finish:
8945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8946    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8947    GOTO_OPCODE(ip)                     @ jump to next instruction
8948
8949
8950/* continuation for OP_EXECUTE_INLINE */
8951
8952    /*
8953     * Extract args, call function.
8954     *  r0 = #of args (0-4)
8955     *  r10 = call index
8956     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8957     *
8958     * Other ideas:
8959     * - Use a jump table from the main piece to jump directly into the
8960     *   AND/LDR pairs.  Costs a data load, saves a branch.
8961     * - Have five separate pieces that do the loading, so we can work the
8962     *   interleave a little better.  Increases code size.
8963     */
8964.LOP_EXECUTE_INLINE_continue:
8965    rsb     r0, r0, #4                  @ r0<- 4-r0
8966    FETCH(r9, 2)                        @ r9<- FEDC
8967    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8968    bl      common_abort                @ (skipped due to ARM prefetch)
89694:  and     ip, r9, #0xf000             @ isolate F
8970    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89713:  and     ip, r9, #0x0f00             @ isolate E
8972    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89732:  and     ip, r9, #0x00f0             @ isolate D
8974    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
89751:  and     ip, r9, #0x000f             @ isolate C
8976    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
89770:
8978    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8979    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8980    @ (not reached)
8981
8982.LOP_EXECUTE_INLINE_table:
8983    .word   gDvmInlineOpsTable
8984
8985
8986    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8987    .global dvmAsmSisterEnd
8988dvmAsmSisterEnd:
8989
8990/* File: armv5te/footer.S */
8991
8992/*
8993 * ===========================================================================
8994 *  Common subroutines and data
8995 * ===========================================================================
8996 */
8997
8998
8999
9000    .text
9001    .align  2
9002
9003#if defined(WITH_JIT)
9004/*
9005 * Return from the translation cache to the interpreter when the compiler is
9006 * having issues translating/executing a Dalvik instruction. We have to skip
9007 * the code cache lookup otherwise it is possible to indefinitely bouce
9008 * between the interpreter and the code cache if the instruction that fails
9009 * to be compiled happens to be at a trace start.
9010 */
9011    .global dvmJitToInterpPunt
9012dvmJitToInterpPunt:
9013    mov    rPC, r0
9014#ifdef EXIT_STATS
9015    mov    r0,lr
9016    bl     dvmBumpPunt;
9017#endif
9018    EXPORT_PC()
9019    adrl   rIBASE, dvmAsmInstructionStart
9020    FETCH_INST()
9021    GET_INST_OPCODE(ip)
9022    GOTO_OPCODE(ip)
9023
9024/*
9025 * Return to the interpreter to handle a single instruction.
9026 * On entry:
9027 *    r0 <= PC
9028 *    r1 <= PC of resume instruction
9029 *    lr <= resume point in translation
9030 */
9031    .global dvmJitToInterpSingleStep
9032dvmJitToInterpSingleStep:
9033    str    lr,[rGLUE,#offGlue_jitResume]
9034    str    r1,[rGLUE,#offGlue_jitResumePC]
9035    mov    r1,#kInterpEntryInstr
9036    @ enum is 4 byte in aapcs-EABI
9037    str    r1, [rGLUE, #offGlue_entryPoint]
9038    mov    rPC,r0
9039    EXPORT_PC()
9040    adrl   rIBASE, dvmAsmInstructionStart
9041    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9042    str    r2,[rGLUE,#offGlue_jitState]
9043    mov    r1,#1                  @ set changeInterp to bail to debug interp
9044    b      common_gotoBail
9045
9046
9047/*
9048 * Return from the translation cache and immediately request
9049 * a translation for the exit target.  Commonly used following
9050 * invokes.
9051 */
9052    .global dvmJitToTraceSelect
9053dvmJitToTraceSelect:
9054    ldr    rPC,[r14, #-1]           @ get our target PC
9055    add    rINST,r14,#-5            @ save start of chain branch
9056    mov    r0,rPC
9057    bl     dvmJitGetCodeAddr        @ Is there a translation?
9058    cmp    r0,#0
9059    beq    2f
9060    mov    r1,rINST
9061    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9062    cmp    r0,#0                    @ successful chain?
9063    bxne   r0                       @ continue native execution
9064    b      toInterpreter            @ didn't chain - resume with interpreter
9065
9066/* No translation, so request one if profiling isn't disabled*/
90672:
9068    adrl   rIBASE, dvmAsmInstructionStart
9069    GET_JIT_PROF_TABLE(r0)
9070    FETCH_INST()
9071    cmp    r0, #0
9072    bne    common_selectTrace
9073    GET_INST_OPCODE(ip)
9074    GOTO_OPCODE(ip)
9075
9076/*
9077 * Return from the translation cache to the interpreter.
9078 * The return was done with a BLX from thumb mode, and
9079 * the following 32-bit word contains the target rPC value.
9080 * Note that lr (r14) will have its low-order bit set to denote
9081 * its thumb-mode origin.
9082 *
9083 * We'll need to stash our lr origin away, recover the new
9084 * target and then check to see if there is a translation available
9085 * for our new target.  If so, we do a translation chain and
9086 * go back to native execution.  Otherwise, it's back to the
9087 * interpreter (after treating this entry as a potential
9088 * trace start).
9089 */
9090    .global dvmJitToInterpNormal
9091dvmJitToInterpNormal:
9092    ldr    rPC,[r14, #-1]           @ get our target PC
9093    add    rINST,r14,#-5            @ save start of chain branch
9094#ifdef EXIT_STATS
9095    bl     dvmBumpNormal
9096#endif
9097    mov    r0,rPC
9098    bl     dvmJitGetCodeAddr        @ Is there a translation?
9099    cmp    r0,#0
9100    beq    toInterpreter            @ go if not, otherwise do chain
9101    mov    r1,rINST
9102    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9103    cmp    r0,#0                    @ successful chain?
9104    bxne   r0                       @ continue native execution
9105    b      toInterpreter            @ didn't chain - resume with interpreter
9106
9107/*
9108 * Return from the translation cache to the interpreter to do method invocation.
9109 * Check if translation exists for the callee, but don't chain to it.
9110 */
9111    .global dvmJitToInterpNoChain
9112dvmJitToInterpNoChain:
9113#ifdef EXIT_STATS
9114    bl     dvmBumpNoChain
9115#endif
9116    mov    r0,rPC
9117    bl     dvmJitGetCodeAddr        @ Is there a translation?
9118    cmp    r0,#0
9119    bxne   r0                       @ continue native execution if so
9120
9121/*
9122 * No translation, restore interpreter regs and start interpreting.
9123 * rGLUE & rFP were preserved in the translated code, and rPC has
9124 * already been restored by the time we get here.  We'll need to set
9125 * up rIBASE & rINST, and load the address of the JitTable into r0.
9126 */
9127toInterpreter:
9128    EXPORT_PC()
9129    adrl   rIBASE, dvmAsmInstructionStart
9130    FETCH_INST()
9131    GET_JIT_PROF_TABLE(r0)
9132    @ NOTE: intended fallthrough
9133/*
9134 * Common code to update potential trace start counter, and initiate
9135 * a trace-build if appropriate.  On entry, rPC should point to the
9136 * next instruction to execute, and rINST should be already loaded with
9137 * the next opcode word, and r0 holds a pointer to the jit profile
9138 * table (pJitProfTable).
9139 */
9140common_testUpdateProfile:
9141    cmp     r0,#0
9142    GET_INST_OPCODE(ip)
9143    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9144
9145common_updateProfile:
9146    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9147    lsl     r3,r3,#23          @ shift out excess 511
9148    ldrb    r1,[r0,r3,lsr #23] @ get counter
9149    GET_INST_OPCODE(ip)
9150    subs    r1,r1,#1           @ decrement counter
9151    strb    r1,[r0,r3,lsr #23] @ and store it
9152    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9153
9154/*
9155 * Here, we switch to the debug interpreter to request
9156 * trace selection.  First, though, check to see if there
9157 * is already a native translation in place (and, if so,
9158 * jump to it now).
9159 */
9160    mov     r1,#255
9161    strb    r1,[r0,r3,lsr #23] @ reset counter
9162    EXPORT_PC()
9163    mov     r0,rPC
9164    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9165    cmp     r0,#0
9166    beq     common_selectTrace
9167    bxne    r0                          @ jump to the translation
9168common_selectTrace:
9169    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9170    str     r2,[rGLUE,#offGlue_jitState]
9171    mov     r1,#1                       @ set changeInterp
9172    b       common_gotoBail
9173
9174#endif
9175
9176/*
9177 * Common code when a backward branch is taken.
9178 *
9179 * On entry:
9180 *  r9 is PC adjustment *in bytes*
9181 */
9182common_backwardBranch:
9183    mov     r0, #kInterpEntryInstr
9184    bl      common_periodicChecks
9185#if defined(WITH_JIT)
9186    GET_JIT_PROF_TABLE(r0)
9187    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9188    cmp     r0,#0
9189    bne     common_updateProfile
9190    GET_INST_OPCODE(ip)
9191    GOTO_OPCODE(ip)
9192#else
9193    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9194    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9195    GOTO_OPCODE(ip)                     @ jump to next instruction
9196#endif
9197
9198
9199/*
9200 * Need to see if the thread needs to be suspended or debugger/profiler
9201 * activity has begun.
9202 *
9203 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9204 * have to do the second ldr.
9205 *
9206 * TODO: reduce this so we're just checking a single location.
9207 *
9208 * On entry:
9209 *  r0 is reentry type, e.g. kInterpEntryInstr
9210 *  r9 is trampoline PC adjustment *in bytes*
9211 */
9212common_periodicChecks:
9213    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9214
9215#if defined(WITH_DEBUGGER)
9216    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9217#endif
9218#if defined(WITH_PROFILER)
9219    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9220#endif
9221
9222    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9223
9224#if defined(WITH_DEBUGGER)
9225    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9226#endif
9227#if defined (WITH_PROFILER)
9228    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9229#endif
9230
9231    cmp     r3, #0                      @ suspend pending?
9232    bne     2f                          @ yes, do full suspension check
9233
9234#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9235# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9236    orrs    r1, r1, r2                  @ r1<- r1 | r2
9237    cmp     r1, #0                      @ debugger attached or profiler started?
9238# elif defined(WITH_DEBUGGER)
9239    cmp     r1, #0                      @ debugger attached?
9240# elif defined(WITH_PROFILER)
9241    cmp     r2, #0                      @ profiler started?
9242# endif
9243    bne     3f                          @ debugger/profiler, switch interp
9244#endif
9245
9246    bx      lr                          @ nothing to do, return
9247
92482:  @ check suspend
9249    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9250    EXPORT_PC()                         @ need for precise GC
9251    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9252
92533:  @ debugger/profiler enabled, bail out
9254    add     rPC, rPC, r9                @ update rPC
9255    str     r0, [rGLUE, #offGlue_entryPoint]
9256    mov     r1, #1                      @ "want switch" = true
9257    b       common_gotoBail
9258
9259
9260/*
9261 * The equivalent of "goto bail", this calls through the "bail handler".
9262 *
9263 * State registers will be saved to the "glue" area before bailing.
9264 *
9265 * On entry:
9266 *  r1 is "bool changeInterp", indicating if we want to switch to the
9267 *     other interpreter or just bail all the way out
9268 */
9269common_gotoBail:
9270    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9271    mov     r0, rGLUE                   @ r0<- glue ptr
9272    b       dvmMterpStdBail             @ call(glue, changeInterp)
9273
9274    @add     r1, r1, #1                  @ using (boolean+1)
9275    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9276    @bl      _longjmp                    @ does not return
9277    @bl      common_abort
9278
9279
9280/*
9281 * Common code for method invocation with range.
9282 *
9283 * On entry:
9284 *  r0 is "Method* methodToCall", the method we're trying to call
9285 */
9286common_invokeMethodRange:
9287.LinvokeNewRange:
9288    @ prepare to copy args to "outs" area of current frame
9289    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9290    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9291    beq     .LinvokeArgsDone            @ if no args, skip the rest
9292    FETCH(r1, 2)                        @ r1<- CCCC
9293
9294    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9295    @ (very few methods have > 10 args; could unroll for common cases)
9296    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9297    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9298    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
92991:  ldr     r1, [r3], #4                @ val = *fp++
9300    subs    r2, r2, #1                  @ count--
9301    str     r1, [r10], #4               @ *outs++ = val
9302    bne     1b                          @ ...while count != 0
9303    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9304    b       .LinvokeArgsDone
9305
9306/*
9307 * Common code for method invocation without range.
9308 *
9309 * On entry:
9310 *  r0 is "Method* methodToCall", the method we're trying to call
9311 */
9312common_invokeMethodNoRange:
9313.LinvokeNewNoRange:
9314    @ prepare to copy args to "outs" area of current frame
9315    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9316    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9317    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9318    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9319    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9320    beq     .LinvokeArgsDone
9321
9322    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9323.LinvokeNonRange:
9324    rsb     r2, r2, #5                  @ r2<- 5-r2
9325    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9326    bl      common_abort                @ (skipped due to ARM prefetch)
93275:  and     ip, rINST, #0x0f00          @ isolate A
9328    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9329    mov     r0, r0                      @ nop
9330    str     r2, [r10, #-4]!             @ *--outs = vA
93314:  and     ip, r1, #0xf000             @ isolate G
9332    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9333    mov     r0, r0                      @ nop
9334    str     r2, [r10, #-4]!             @ *--outs = vG
93353:  and     ip, r1, #0x0f00             @ isolate F
9336    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9337    mov     r0, r0                      @ nop
9338    str     r2, [r10, #-4]!             @ *--outs = vF
93392:  and     ip, r1, #0x00f0             @ isolate E
9340    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9341    mov     r0, r0                      @ nop
9342    str     r2, [r10, #-4]!             @ *--outs = vE
93431:  and     ip, r1, #0x000f             @ isolate D
9344    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9345    mov     r0, r0                      @ nop
9346    str     r2, [r10, #-4]!             @ *--outs = vD
93470:  @ fall through to .LinvokeArgsDone
9348
9349.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9350    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9351    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9352    @ find space for the new stack frame, check for overflow
9353    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9354    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9355    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9356@    bl      common_dumpRegs
9357    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9358    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9359    cmp     r3, r9                      @ bottom < interpStackEnd?
9360    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9361    blt     .LstackOverflow             @ yes, this frame will overflow stack
9362
9363    @ set up newSaveArea
9364#ifdef EASY_GDB
9365    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9366    str     ip, [r10, #offStackSaveArea_prevSave]
9367#endif
9368    str     rFP, [r10, #offStackSaveArea_prevFrame]
9369    str     rPC, [r10, #offStackSaveArea_savedPc]
9370#if defined(WITH_JIT)
9371    mov     r9, #0
9372    str     r9, [r10, #offStackSaveArea_returnAddr]
9373#endif
9374    str     r0, [r10, #offStackSaveArea_method]
9375    tst     r3, #ACC_NATIVE
9376    bne     .LinvokeNative
9377
9378    /*
9379    stmfd   sp!, {r0-r3}
9380    bl      common_printNewline
9381    mov     r0, rFP
9382    mov     r1, #0
9383    bl      dvmDumpFp
9384    ldmfd   sp!, {r0-r3}
9385    stmfd   sp!, {r0-r3}
9386    mov     r0, r1
9387    mov     r1, r10
9388    bl      dvmDumpFp
9389    bl      common_printNewline
9390    ldmfd   sp!, {r0-r3}
9391    */
9392
9393    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9394    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9395    mov     rPC, r2                         @ publish new rPC
9396    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9397
9398    @ Update "glue" values for the new method
9399    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9400    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9401    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9402#if defined(WITH_JIT)
9403    GET_JIT_PROF_TABLE(r0)
9404    mov     rFP, r1                         @ fp = newFp
9405    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9406    mov     rINST, r9                       @ publish new rINST
9407    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9408    cmp     r0,#0
9409    bne     common_updateProfile
9410    GOTO_OPCODE(ip)                         @ jump to next instruction
9411#else
9412    mov     rFP, r1                         @ fp = newFp
9413    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9414    mov     rINST, r9                       @ publish new rINST
9415    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9416    GOTO_OPCODE(ip)                         @ jump to next instruction
9417#endif
9418
9419.LinvokeNative:
9420    @ Prep for the native call
9421    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9422    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9423    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9424    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9425    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9426    mov     r9, r3                      @ r9<- glue->self (preserve)
9427
9428    mov     r2, r0                      @ r2<- methodToCall
9429    mov     r0, r1                      @ r0<- newFp (points to args)
9430    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9431
9432#ifdef ASSIST_DEBUGGER
9433    /* insert fake function header to help gdb find the stack frame */
9434    b       .Lskip
9435    .type   dalvik_mterp, %function
9436dalvik_mterp:
9437    .fnstart
9438    MTERP_ENTRY1
9439    MTERP_ENTRY2
9440.Lskip:
9441#endif
9442
9443    @mov     lr, pc                      @ set return addr
9444    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9445    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9446
9447    @ native return; r9=self, r10=newSaveArea
9448    @ equivalent to dvmPopJniLocals
9449    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9450    ldr     r1, [r9, #offThread_exception] @ check for exception
9451    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9452    cmp     r1, #0                      @ null?
9453    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9454    bne     common_exceptionThrown      @ no, handle exception
9455
9456    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9458    GOTO_OPCODE(ip)                     @ jump to next instruction
9459
9460.LstackOverflow:
9461    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9462    bl      dvmHandleStackOverflow
9463    b       common_exceptionThrown
9464#ifdef ASSIST_DEBUGGER
9465    .fnend
9466#endif
9467
9468
9469    /*
9470     * Common code for method invocation, calling through "glue code".
9471     *
9472     * TODO: now that we have range and non-range invoke handlers, this
9473     *       needs to be split into two.  Maybe just create entry points
9474     *       that set r9 and jump here?
9475     *
9476     * On entry:
9477     *  r0 is "Method* methodToCall", the method we're trying to call
9478     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9479     */
9480     .if    0
9481.LinvokeOld:
9482    sub     sp, sp, #8                  @ space for args + pad
9483    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9484    mov     r2, r0                      @ A2<- methodToCall
9485    mov     r0, rGLUE                   @ A0<- glue
9486    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9487    mov     r1, r9                      @ A1<- methodCallRange
9488    mov     r3, rINST, lsr #8           @ A3<- AA
9489    str     ip, [sp, #0]                @ A4<- ip
9490    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9491    add     sp, sp, #8                  @ remove arg area
9492    b       common_resumeAfterGlueCall  @ continue to next instruction
9493    .endif
9494
9495
9496
9497/*
9498 * Common code for handling a return instruction.
9499 *
9500 * This does not return.
9501 */
9502common_returnFromMethod:
9503.LreturnNew:
9504    mov     r0, #kInterpEntryReturn
9505    mov     r9, #0
9506    bl      common_periodicChecks
9507
9508    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9509    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9510    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9511    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9512                                        @ r2<- method we're returning to
9513    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9514    cmp     r2, #0                      @ is this a break frame?
9515    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9516    mov     r1, #0                      @ "want switch" = false
9517    beq     common_gotoBail             @ break frame, bail out completely
9518
9519    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9520    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9521    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9522    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9523#if defined(WITH_JIT)
9524    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
9525    GET_JIT_PROF_TABLE(r0)
9526    mov     rPC, r9                     @ publish new rPC
9527    str     r1, [rGLUE, #offGlue_methodClassDex]
9528    cmp     r3, #0                      @ caller is compiled code
9529    blxne   r3
9530    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9531    cmp     r0,#0
9532    bne     common_updateProfile
9533    GOTO_OPCODE(ip)                     @ jump to next instruction
9534#else
9535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9536    mov     rPC, r9                     @ publish new rPC
9537    str     r1, [rGLUE, #offGlue_methodClassDex]
9538    GOTO_OPCODE(ip)                     @ jump to next instruction
9539#endif
9540
9541    /*
9542     * Return handling, calls through "glue code".
9543     */
9544     .if    0
9545.LreturnOld:
9546    SAVE_PC_FP_TO_GLUE()                @ export state
9547    mov     r0, rGLUE                   @ arg to function
9548    bl      dvmMterp_returnFromMethod
9549    b       common_resumeAfterGlueCall
9550    .endif
9551
9552
9553/*
9554 * Somebody has thrown an exception.  Handle it.
9555 *
9556 * If the exception processing code returns to us (instead of falling
9557 * out of the interpreter), continue with whatever the next instruction
9558 * now happens to be.
9559 *
9560 * This does not return.
9561 */
9562     .global dvmMterpCommonExceptionThrown
9563dvmMterpCommonExceptionThrown:
9564common_exceptionThrown:
9565.LexceptionNew:
9566    mov     r0, #kInterpEntryThrow
9567    mov     r9, #0
9568    bl      common_periodicChecks
9569
9570#if defined(WITH_JIT)
9571    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9572    str     r2,[rGLUE,#offGlue_jitState]
9573#endif
9574
9575    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9576    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9577    mov     r1, r10                     @ r1<- self
9578    mov     r0, r9                      @ r0<- exception
9579    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9580    mov     r3, #0                      @ r3<- NULL
9581    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9582
9583    /* set up args and a local for "&fp" */
9584    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9585    str     rFP, [sp, #-4]!             @ *--sp = fp
9586    mov     ip, sp                      @ ip<- &fp
9587    mov     r3, #0                      @ r3<- false
9588    str     ip, [sp, #-4]!              @ *--sp = &fp
9589    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9590    mov     r0, r10                     @ r0<- self
9591    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9592    mov     r2, r9                      @ r2<- exception
9593    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9594    mov     r1, r1, asr #1              @ r1<- offset in code units
9595
9596    /* call, r0 gets catchRelPc (a code-unit offset) */
9597    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9598
9599    /* fix earlier stack overflow if necessary; may trash rFP */
9600    ldrb    r1, [r10, #offThread_stackOverflowed]
9601    cmp     r1, #0                      @ did we overflow earlier?
9602    beq     1f                          @ no, skip ahead
9603    mov     rFP, r0                     @ save relPc result in rFP
9604    mov     r0, r10                     @ r0<- self
9605    bl      dvmCleanupStackOverflow     @ call(self)
9606    mov     r0, rFP                     @ restore result
96071:
9608
9609    /* update frame pointer and check result from dvmFindCatchBlock */
9610    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9611    cmp     r0, #0                      @ is catchRelPc < 0?
9612    add     sp, sp, #8                  @ restore stack
9613    bmi     .LnotCaughtLocally
9614
9615    /* adjust locals to match self->curFrame and updated PC */
9616    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9617    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9618    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9619    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9620    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9621    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9622    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9623    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9624
9625    /* release the tracked alloc on the exception */
9626    mov     r0, r9                      @ r0<- exception
9627    mov     r1, r10                     @ r1<- self
9628    bl      dvmReleaseTrackedAlloc      @ release the exception
9629
9630    /* restore the exception if the handler wants it */
9631    FETCH_INST()                        @ load rINST from rPC
9632    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9633    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9634    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9635    GOTO_OPCODE(ip)                     @ jump to next instruction
9636
9637.LnotCaughtLocally: @ r9=exception, r10=self
9638    /* fix stack overflow if necessary */
9639    ldrb    r1, [r10, #offThread_stackOverflowed]
9640    cmp     r1, #0                      @ did we overflow earlier?
9641    movne   r0, r10                     @ if yes: r0<- self
9642    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9643
9644    @ may want to show "not caught locally" debug messages here
9645#if DVM_SHOW_EXCEPTION >= 2
9646    /* call __android_log_print(prio, tag, format, ...) */
9647    /* "Exception %s from %s:%d not caught locally" */
9648    @ dvmLineNumFromPC(method, pc - method->insns)
9649    ldr     r0, [rGLUE, #offGlue_method]
9650    ldr     r1, [r0, #offMethod_insns]
9651    sub     r1, rPC, r1
9652    asr     r1, r1, #1
9653    bl      dvmLineNumFromPC
9654    str     r0, [sp, #-4]!
9655    @ dvmGetMethodSourceFile(method)
9656    ldr     r0, [rGLUE, #offGlue_method]
9657    bl      dvmGetMethodSourceFile
9658    str     r0, [sp, #-4]!
9659    @ exception->clazz->descriptor
9660    ldr     r3, [r9, #offObject_clazz]
9661    ldr     r3, [r3, #offClassObject_descriptor]
9662    @
9663    ldr     r2, strExceptionNotCaughtLocally
9664    ldr     r1, strLogTag
9665    mov     r0, #3                      @ LOG_DEBUG
9666    bl      __android_log_print
9667#endif
9668    str     r9, [r10, #offThread_exception] @ restore exception
9669    mov     r0, r9                      @ r0<- exception
9670    mov     r1, r10                     @ r1<- self
9671    bl      dvmReleaseTrackedAlloc      @ release the exception
9672    mov     r1, #0                      @ "want switch" = false
9673    b       common_gotoBail             @ bail out
9674
9675
9676    /*
9677     * Exception handling, calls through "glue code".
9678     */
9679    .if     0
9680.LexceptionOld:
9681    SAVE_PC_FP_TO_GLUE()                @ export state
9682    mov     r0, rGLUE                   @ arg to function
9683    bl      dvmMterp_exceptionThrown
9684    b       common_resumeAfterGlueCall
9685    .endif
9686
9687
9688/*
9689 * After returning from a "glued" function, pull out the updated
9690 * values and start executing at the next instruction.
9691 */
9692common_resumeAfterGlueCall:
9693    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9694    FETCH_INST()                        @ load rINST from rPC
9695    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9696    GOTO_OPCODE(ip)                     @ jump to next instruction
9697
9698/*
9699 * Invalid array index.
9700 */
9701common_errArrayIndex:
9702    EXPORT_PC()
9703    ldr     r0, strArrayIndexException
9704    mov     r1, #0
9705    bl      dvmThrowException
9706    b       common_exceptionThrown
9707
9708/*
9709 * Invalid array value.
9710 */
9711common_errArrayStore:
9712    EXPORT_PC()
9713    ldr     r0, strArrayStoreException
9714    mov     r1, #0
9715    bl      dvmThrowException
9716    b       common_exceptionThrown
9717
9718/*
9719 * Integer divide or mod by zero.
9720 */
9721common_errDivideByZero:
9722    EXPORT_PC()
9723    ldr     r0, strArithmeticException
9724    ldr     r1, strDivideByZero
9725    bl      dvmThrowException
9726    b       common_exceptionThrown
9727
9728/*
9729 * Attempt to allocate an array with a negative size.
9730 */
9731common_errNegativeArraySize:
9732    EXPORT_PC()
9733    ldr     r0, strNegativeArraySizeException
9734    mov     r1, #0
9735    bl      dvmThrowException
9736    b       common_exceptionThrown
9737
9738/*
9739 * Invocation of a non-existent method.
9740 */
9741common_errNoSuchMethod:
9742    EXPORT_PC()
9743    ldr     r0, strNoSuchMethodError
9744    mov     r1, #0
9745    bl      dvmThrowException
9746    b       common_exceptionThrown
9747
9748/*
9749 * We encountered a null object when we weren't expecting one.  We
9750 * export the PC, throw a NullPointerException, and goto the exception
9751 * processing code.
9752 */
9753common_errNullObject:
9754    EXPORT_PC()
9755    ldr     r0, strNullPointerException
9756    mov     r1, #0
9757    bl      dvmThrowException
9758    b       common_exceptionThrown
9759
9760/*
9761 * For debugging, cause an immediate fault.  The source address will
9762 * be in lr (use a bl instruction to jump here).
9763 */
9764common_abort:
9765    ldr     pc, .LdeadFood
9766.LdeadFood:
9767    .word   0xdeadf00d
9768
9769/*
9770 * Spit out a "we were here", preserving all registers.  (The attempt
9771 * to save ip won't work, but we need to save an even number of
9772 * registers for EABI 64-bit stack alignment.)
9773 */
9774    .macro  SQUEAK num
9775common_squeak\num:
9776    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9777    ldr     r0, strSqueak
9778    mov     r1, #\num
9779    bl      printf
9780    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9781    bx      lr
9782    .endm
9783
9784    SQUEAK  0
9785    SQUEAK  1
9786    SQUEAK  2
9787    SQUEAK  3
9788    SQUEAK  4
9789    SQUEAK  5
9790
9791/*
9792 * Spit out the number in r0, preserving registers.
9793 */
9794common_printNum:
9795    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9796    mov     r1, r0
9797    ldr     r0, strSqueak
9798    bl      printf
9799    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9800    bx      lr
9801
9802/*
9803 * Print a newline, preserving registers.
9804 */
9805common_printNewline:
9806    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9807    ldr     r0, strNewline
9808    bl      printf
9809    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9810    bx      lr
9811
9812    /*
9813     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9814     */
9815common_printHex:
9816    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9817    mov     r1, r0
9818    ldr     r0, strPrintHex
9819    bl      printf
9820    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9821    bx      lr
9822
9823/*
9824 * Print the 64-bit quantity in r0-r1, preserving registers.
9825 */
9826common_printLong:
9827    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9828    mov     r3, r1
9829    mov     r2, r0
9830    ldr     r0, strPrintLong
9831    bl      printf
9832    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9833    bx      lr
9834
9835/*
9836 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9837 */
9838common_printMethod:
9839    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9840    bl      dvmMterpPrintMethod
9841    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9842    bx      lr
9843
9844/*
9845 * Call a C helper function that dumps regs and possibly some
9846 * additional info.  Requires the C function to be compiled in.
9847 */
9848    .if     0
9849common_dumpRegs:
9850    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9851    bl      dvmMterpDumpArmRegs
9852    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9853    bx      lr
9854    .endif
9855
9856#if 0
9857/*
9858 * Experiment on VFP mode.
9859 *
9860 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
9861 *
9862 * Updates the bits specified by "mask", setting them to the values in "val".
9863 */
9864setFPSCR:
9865    and     r0, r0, r1                  @ make sure no stray bits are set
9866    fmrx    r2, fpscr                   @ get VFP reg
9867    mvn     r1, r1                      @ bit-invert mask
9868    and     r2, r2, r1                  @ clear masked bits
9869    orr     r2, r2, r0                  @ set specified bits
9870    fmxr    fpscr, r2                   @ set VFP reg
9871    mov     r0, r2                      @ return new value
9872    bx      lr
9873
9874    .align  2
9875    .global dvmConfigureFP
9876    .type   dvmConfigureFP, %function
9877dvmConfigureFP:
9878    stmfd   sp!, {ip, lr}
9879    /* 0x03000000 sets DN/FZ */
9880    /* 0x00009f00 clears the six exception enable flags */
9881    bl      common_squeak0
9882    mov     r0, #0x03000000             @ r0<- 0x03000000
9883    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
9884    bl      setFPSCR
9885    ldmfd   sp!, {ip, pc}
9886#endif
9887
9888
9889/*
9890 * String references, must be close to the code that uses them.
9891 */
9892    .align  2
9893strArithmeticException:
9894    .word   .LstrArithmeticException
9895strArrayIndexException:
9896    .word   .LstrArrayIndexException
9897strArrayStoreException:
9898    .word   .LstrArrayStoreException
9899strDivideByZero:
9900    .word   .LstrDivideByZero
9901strNegativeArraySizeException:
9902    .word   .LstrNegativeArraySizeException
9903strNoSuchMethodError:
9904    .word   .LstrNoSuchMethodError
9905strNullPointerException:
9906    .word   .LstrNullPointerException
9907
9908strLogTag:
9909    .word   .LstrLogTag
9910strExceptionNotCaughtLocally:
9911    .word   .LstrExceptionNotCaughtLocally
9912
9913strNewline:
9914    .word   .LstrNewline
9915strSqueak:
9916    .word   .LstrSqueak
9917strPrintHex:
9918    .word   .LstrPrintHex
9919strPrintLong:
9920    .word   .LstrPrintLong
9921
9922/*
9923 * Zero-terminated ASCII string data.
9924 *
9925 * On ARM we have two choices: do like gcc does, and LDR from a .word
9926 * with the address, or use an ADR pseudo-op to get the address
9927 * directly.  ADR saves 4 bytes and an indirection, but it's using a
9928 * PC-relative addressing mode and hence has a limited range, which
9929 * makes it not work well with mergeable string sections.
9930 */
9931    .section .rodata.str1.4,"aMS",%progbits,1
9932
9933.LstrBadEntryPoint:
9934    .asciz  "Bad entry point %d\n"
9935.LstrArithmeticException:
9936    .asciz  "Ljava/lang/ArithmeticException;"
9937.LstrArrayIndexException:
9938    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9939.LstrArrayStoreException:
9940    .asciz  "Ljava/lang/ArrayStoreException;"
9941.LstrClassCastException:
9942    .asciz  "Ljava/lang/ClassCastException;"
9943.LstrDivideByZero:
9944    .asciz  "divide by zero"
9945.LstrFilledNewArrayNotImpl:
9946    .asciz  "filled-new-array only implemented for objects and 'int'"
9947.LstrInternalError:
9948    .asciz  "Ljava/lang/InternalError;"
9949.LstrInstantiationError:
9950    .asciz  "Ljava/lang/InstantiationError;"
9951.LstrNegativeArraySizeException:
9952    .asciz  "Ljava/lang/NegativeArraySizeException;"
9953.LstrNoSuchMethodError:
9954    .asciz  "Ljava/lang/NoSuchMethodError;"
9955.LstrNullPointerException:
9956    .asciz  "Ljava/lang/NullPointerException;"
9957
9958.LstrLogTag:
9959    .asciz  "mterp"
9960.LstrExceptionNotCaughtLocally:
9961    .asciz  "Exception %s from %s:%d not caught locally\n"
9962
9963.LstrNewline:
9964    .asciz  "\n"
9965.LstrSqueak:
9966    .asciz  "<%d>"
9967.LstrPrintHex:
9968    .asciz  "<0x%x>"
9969.LstrPrintLong:
9970    .asciz  "<%lld>"
9971
9972
9973