InterpAsm-armv5te-vfp.S revision 7b133ef7c84e68c3c4042176d830ea5b52e84139
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23/*
24 * ARMv5 definitions and declarations.
25 */
26
27/*
28ARM EABI general notes:
29
30r0-r3 hold first 4 args to a method; they are not preserved across method calls
31r4-r8 are available for general use
32r9 is given special treatment in some situations, but not for us
33r10 (sl) seems to be generally available
34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
35r12 (ip) is scratch -- not preserved across method calls
36r13 (sp) should be managed carefully in case a signal arrives
37r14 (lr) must be preserved
38r15 (pc) can be tinkered with directly
39
40r0 holds returns of <= 4 bytes
41r0-r1 hold returns of 8 bytes, low word in r0
42
43Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
45s0-s15 (d0-d7, q0-a3) do not need to be.
46
47Stack is "full descending".  Only the arguments that don't fit in the first 4
48registers are placed on the stack.  "sp" points at the first stacked argument
49(i.e. the 5th arg).
50
51VFP: single-precision results in s0, double-precision results in d0.
52
53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5464-bit quantities (long long, double) must be 64-bit aligned.
55*/
56
57/*
58Mterp and ARM notes:
59
60The following registers have fixed assignments:
61
62  reg nick      purpose
63  r4  rPC       interpreted program counter, used for fetching instructions
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  rGLUE     MterpGlue pointer
66  r7  rINST     first 16-bit code unit of current instruction
67  r8  rIBASE    interpreted instruction base pointer, used for computed goto
68
69Macros are provided for common operations.  Each macro MUST emit only
70one instruction to make instruction-counting easier.  They MUST NOT alter
71unspecified registers or condition codes.
72*/
73
74/* single-purpose registers, given names for clarity */
75#define rPC     r4
76#define rFP     r5
77#define rGLUE   r6
78#define rINST   r7
79#define rIBASE  r8
80
81/* save/restore the PC and/or FP from the glue struct */
82#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
83#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
84#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
85#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
86#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
87#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
88
89/*
90 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
91 * be done *before* something calls dvmThrowException.
92 *
93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
95 *
96 * It's okay to do this more than once.
97 */
98#define EXPORT_PC() \
99    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
100
101/*
102 * Given a frame pointer, find the stack save area.
103 *
104 * In C this is "((StackSaveArea*)(_fp) -1)".
105 */
106#define SAVEAREA_FROM_FP(_reg, _fpreg) \
107    sub     _reg, _fpreg, #sizeofStackSaveArea
108
109/*
110 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
111 */
112#define FETCH_INST()            ldrh    rINST, [rPC]
113
114/*
115 * Fetch the next instruction from the specified offset.  Advances rPC
116 * to point to the next instruction.  "_count" is in 16-bit code units.
117 *
118 * Because of the limited size of immediate constants on ARM, this is only
119 * suitable for small forward movements (i.e. don't try to implement "goto"
120 * with this).
121 *
122 * This must come AFTER anything that can throw an exception, or the
123 * exception catch may miss.  (This also implies that it must come after
124 * EXPORT_PC().)
125 */
126#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
127
128/*
129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
130 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
131 */
132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
133        ldrh    _dreg, [_sreg, #(_count*2)]!
134
135/*
136 * Fetch the next instruction from an offset specified by _reg.  Updates
137 * rPC to point to the next instruction.  "_reg" must specify the distance
138 * in bytes, *not* 16-bit code units, and may be a signed value.
139 *
140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
141 * bits that hold the shift distance are used for the half/byte/sign flags.
142 * In some cases we can pre-double _reg for free, so we require a byte offset
143 * here.
144 */
145#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
146
147/*
148 * Fetch a half-word code unit from an offset past the current PC.  The
149 * "_count" value is in 16-bit code units.  Does not advance rPC.
150 *
151 * The "_S" variant works the same but treats the value as signed.
152 */
153#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
154#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
155
156/*
157 * Fetch one byte from an offset past the current PC.  Pass in the same
158 * "_count" as you would for FETCH, and an additional 0/1 indicating which
159 * byte of the halfword you want (lo/hi).
160 */
161#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
162
163/*
164 * Put the instruction's opcode field into the specified register.
165 */
166#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
167
168/*
169 * Put the prefetched instruction's opcode field into the specified register.
170 */
171#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
172
173/*
174 * Begin executing the opcode in _reg.  Because this only jumps within the
175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
176 */
177#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
178#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
180
181/*
182 * Get/set the 32-bit value from a Dalvik register.
183 */
184#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
185#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
186
187#if defined(WITH_JIT)
188#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
189#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
190#endif
191
192/*
193 * Convert a virtual register index into an address.
194 */
195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
196        add     _reg, rFP, _vreg, lsl #2
197
198/*
199 * This is a #include, not a %include, because we want the C pre-processor
200 * to expand the macros into assembler assignment statements.
201 */
202#include "../common/asm-constants.h"
203
204#if defined(WITH_JIT)
205#include "../common/jit-config.h"
206#endif
207
208/* File: armv5te/platform.S */
209/*
210 * ===========================================================================
211 *  CPU-version-specific defines
212 * ===========================================================================
213 */
214
215/*
216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
217 * one-way branch.
218 *
219 * May modify IP.  Does not modify LR.
220 */
221.macro  LDR_PC source
222    ldr     pc, \source
223.endm
224
225/*
226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
227 * Jump to subroutine.
228 *
229 * May modify IP and LR.
230 */
231.macro  LDR_PC_LR source
232    mov     lr, pc
233    ldr     pc, \source
234.endm
235
236/*
237 * Macro for "LDMFD SP!, {...regs...,PC}".
238 *
239 * May modify IP and LR.
240 */
241.macro  LDMFD_PC regs
242    ldmfd   sp!, {\regs,pc}
243.endm
244
245
246/* File: armv5te/entry.S */
247/*
248 * Copyright (C) 2008 The Android Open Source Project
249 *
250 * Licensed under the Apache License, Version 2.0 (the "License");
251 * you may not use this file except in compliance with the License.
252 * You may obtain a copy of the License at
253 *
254 *      http://www.apache.org/licenses/LICENSE-2.0
255 *
256 * Unless required by applicable law or agreed to in writing, software
257 * distributed under the License is distributed on an "AS IS" BASIS,
258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259 * See the License for the specific language governing permissions and
260 * limitations under the License.
261 */
262/*
263 * Interpreter entry point.
264 */
265
266/*
267 * We don't have formal stack frames, so gdb scans upward in the code
268 * to find the start of the function (a label with the %function type),
269 * and then looks at the next few instructions to figure out what
270 * got pushed onto the stack.  From this it figures out how to restore
271 * the registers, including PC, for the previous stack frame.  If gdb
272 * sees a non-function label, it stops scanning, so either we need to
273 * have nothing but assembler-local labels between the entry point and
274 * the break, or we need to fake it out.
275 *
276 * When this is defined, we add some stuff to make gdb less confused.
277 */
278#define ASSIST_DEBUGGER 1
279
280    .text
281    .align  2
282    .global dvmMterpStdRun
283    .type   dvmMterpStdRun, %function
284
285/*
286 * On entry:
287 *  r0  MterpGlue* glue
288 *
289 * This function returns a boolean "changeInterp" value.  The return comes
290 * via a call to dvmMterpStdBail().
291 */
292dvmMterpStdRun:
293#define MTERP_ENTRY1 \
294    .save {r4-r10,fp,lr}; \
295    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
296#define MTERP_ENTRY2 \
297    .pad    #4; \
298    sub     sp, sp, #4                  @ align 64
299
300    .fnstart
301    MTERP_ENTRY1
302    MTERP_ENTRY2
303
304    /* save stack pointer, add magic word for debuggerd */
305    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
306
307    /* set up "named" registers, figure out entry point */
308    mov     rGLUE, r0                   @ set rGLUE
309    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
310    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
311    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
312    cmp     r1, #kInterpEntryInstr      @ usual case?
313    bne     .Lnot_instr                 @ no, handle it
314
315#if defined(WITH_JIT)
316.Lno_singleStep:
317    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
318    /* Entry is always a possible trace start */
319    GET_JIT_PROF_TABLE(r0)
320    FETCH_INST()
321    mov    r1, #0                       @ prepare the value for the new state
322    str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
323    cmp    r0,#0
324    bne    common_updateProfile
325    GET_INST_OPCODE(ip)
326    GOTO_OPCODE(ip)
327#else
328    /* start executing the instruction at rPC */
329    FETCH_INST()                        @ load rINST from rPC
330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
331    GOTO_OPCODE(ip)                     @ jump to next instruction
332#endif
333
334.Lnot_instr:
335    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
336    beq     common_returnFromMethod
337
338.Lnot_return:
339    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
340    beq     common_exceptionThrown
341
342#if defined(WITH_JIT)
343.Lnot_throw:
344    ldr     r0,[rGLUE, #offGlue_jitResume]
345    ldr     r2,[rGLUE, #offGlue_jitResumePC]
346    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
347    bne     .Lbad_arg
348    cmp     rPC,r2
349    bne     .Lno_singleStep             @ must have branched, don't resume
350    mov     r1, #kInterpEntryInstr
351    strb    r1, [rGLUE, #offGlue_entryPoint]
352    ldr     rINST, .LdvmCompilerTemplate
353    bx      r0                          @ re-enter the translation
354.LdvmCompilerTemplate:
355    .word   dvmCompilerTemplateStart
356#endif
357
358.Lbad_arg:
359    ldr     r0, strBadEntryPoint
360    @ r1 holds value of entryPoint
361    bl      printf
362    bl      dvmAbort
363    .fnend
364
365
366    .global dvmMterpStdBail
367    .type   dvmMterpStdBail, %function
368
369/*
370 * Restore the stack pointer and PC from the save point established on entry.
371 * This is essentially the same as a longjmp, but should be cheaper.  The
372 * last instruction causes us to return to whoever called dvmMterpStdRun.
373 *
374 * We pushed some registers on the stack in dvmMterpStdRun, then saved
375 * SP and LR.  Here we restore SP, restore the registers, and then restore
376 * LR to PC.
377 *
378 * On entry:
379 *  r0  MterpGlue* glue
380 *  r1  bool changeInterp
381 */
382dvmMterpStdBail:
383    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
384    mov     r0, r1                          @ return the changeInterp value
385    add     sp, sp, #4                      @ un-align 64
386    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
387
388
389/*
390 * String references.
391 */
392strBadEntryPoint:
393    .word   .LstrBadEntryPoint
394
395
396
397    .global dvmAsmInstructionStart
398    .type   dvmAsmInstructionStart, %function
399dvmAsmInstructionStart = .L_OP_NOP
400    .text
401
402/* ------------------------------ */
403    .balign 64
404.L_OP_NOP: /* 0x00 */
405/* File: armv5te/OP_NOP.S */
406    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
407    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
408    GOTO_OPCODE(ip)                     @ execute it
409
410#ifdef ASSIST_DEBUGGER
411    /* insert fake function header to help gdb find the stack frame */
412    .type   dalvik_inst, %function
413dalvik_inst:
414    .fnstart
415    MTERP_ENTRY1
416    MTERP_ENTRY2
417    .fnend
418#endif
419
420
421/* ------------------------------ */
422    .balign 64
423.L_OP_MOVE: /* 0x01 */
424/* File: armv5te/OP_MOVE.S */
425    /* for move, move-object, long-to-int */
426    /* op vA, vB */
427    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
428    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
429    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
430    GET_VREG(r2, r1)                    @ r2<- fp[B]
431    and     r0, r0, #15
432    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
433    SET_VREG(r2, r0)                    @ fp[A]<- r2
434    GOTO_OPCODE(ip)                     @ execute next instruction
435
436
437/* ------------------------------ */
438    .balign 64
439.L_OP_MOVE_FROM16: /* 0x02 */
440/* File: armv5te/OP_MOVE_FROM16.S */
441    /* for: move/from16, move-object/from16 */
442    /* op vAA, vBBBB */
443    FETCH(r1, 1)                        @ r1<- BBBB
444    mov     r0, rINST, lsr #8           @ r0<- AA
445    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
446    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
448    SET_VREG(r2, r0)                    @ fp[AA]<- r2
449    GOTO_OPCODE(ip)                     @ jump to next instruction
450
451
452/* ------------------------------ */
453    .balign 64
454.L_OP_MOVE_16: /* 0x03 */
455/* File: armv5te/OP_MOVE_16.S */
456    /* for: move/16, move-object/16 */
457    /* op vAAAA, vBBBB */
458    FETCH(r1, 2)                        @ r1<- BBBB
459    FETCH(r0, 1)                        @ r0<- AAAA
460    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
461    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
462    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
463    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
464    GOTO_OPCODE(ip)                     @ jump to next instruction
465
466
467/* ------------------------------ */
468    .balign 64
469.L_OP_MOVE_WIDE: /* 0x04 */
470/* File: armv5te/OP_MOVE_WIDE.S */
471    /* move-wide vA, vB */
472    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
473    mov     r2, rINST, lsr #8           @ r2<- A(+)
474    mov     r3, rINST, lsr #12          @ r3<- B
475    and     r2, r2, #15
476    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
477    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
478    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
479    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
480    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
481    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
482    GOTO_OPCODE(ip)                     @ jump to next instruction
483
484
485/* ------------------------------ */
486    .balign 64
487.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
488/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
489    /* move-wide/from16 vAA, vBBBB */
490    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
491    FETCH(r3, 1)                        @ r3<- BBBB
492    mov     r2, rINST, lsr #8           @ r2<- AA
493    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
494    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
495    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
496    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
497    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
498    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
499    GOTO_OPCODE(ip)                     @ jump to next instruction
500
501
502/* ------------------------------ */
503    .balign 64
504.L_OP_MOVE_WIDE_16: /* 0x06 */
505/* File: armv5te/OP_MOVE_WIDE_16.S */
506    /* move-wide/16 vAAAA, vBBBB */
507    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
508    FETCH(r3, 2)                        @ r3<- BBBB
509    FETCH(r2, 1)                        @ r2<- AAAA
510    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
511    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
512    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
513    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
514    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
515    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
516    GOTO_OPCODE(ip)                     @ jump to next instruction
517
518
519/* ------------------------------ */
520    .balign 64
521.L_OP_MOVE_OBJECT: /* 0x07 */
522/* File: armv5te/OP_MOVE_OBJECT.S */
523/* File: armv5te/OP_MOVE.S */
524    /* for move, move-object, long-to-int */
525    /* op vA, vB */
526    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
527    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
528    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
529    GET_VREG(r2, r1)                    @ r2<- fp[B]
530    and     r0, r0, #15
531    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
532    SET_VREG(r2, r0)                    @ fp[A]<- r2
533    GOTO_OPCODE(ip)                     @ execute next instruction
534
535
536
537/* ------------------------------ */
538    .balign 64
539.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
540/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
541/* File: armv5te/OP_MOVE_FROM16.S */
542    /* for: move/from16, move-object/from16 */
543    /* op vAA, vBBBB */
544    FETCH(r1, 1)                        @ r1<- BBBB
545    mov     r0, rINST, lsr #8           @ r0<- AA
546    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
547    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
549    SET_VREG(r2, r0)                    @ fp[AA]<- r2
550    GOTO_OPCODE(ip)                     @ jump to next instruction
551
552
553
554/* ------------------------------ */
555    .balign 64
556.L_OP_MOVE_OBJECT_16: /* 0x09 */
557/* File: armv5te/OP_MOVE_OBJECT_16.S */
558/* File: armv5te/OP_MOVE_16.S */
559    /* for: move/16, move-object/16 */
560    /* op vAAAA, vBBBB */
561    FETCH(r1, 2)                        @ r1<- BBBB
562    FETCH(r0, 1)                        @ r0<- AAAA
563    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
564    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
565    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
566    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
567    GOTO_OPCODE(ip)                     @ jump to next instruction
568
569
570
571/* ------------------------------ */
572    .balign 64
573.L_OP_MOVE_RESULT: /* 0x0a */
574/* File: armv5te/OP_MOVE_RESULT.S */
575    /* for: move-result, move-result-object */
576    /* op vAA */
577    mov     r2, rINST, lsr #8           @ r2<- AA
578    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
579    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
580    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
581    SET_VREG(r0, r2)                    @ fp[AA]<- r0
582    GOTO_OPCODE(ip)                     @ jump to next instruction
583
584
585/* ------------------------------ */
586    .balign 64
587.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
588/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
589    /* move-result-wide vAA */
590    mov     r2, rINST, lsr #8           @ r2<- AA
591    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
592    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
593    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
594    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
597    GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600/* ------------------------------ */
601    .balign 64
602.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
603/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
604/* File: armv5te/OP_MOVE_RESULT.S */
605    /* for: move-result, move-result-object */
606    /* op vAA */
607    mov     r2, rINST, lsr #8           @ r2<- AA
608    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
609    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
610    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
611    SET_VREG(r0, r2)                    @ fp[AA]<- r0
612    GOTO_OPCODE(ip)                     @ jump to next instruction
613
614
615
616/* ------------------------------ */
617    .balign 64
618.L_OP_MOVE_EXCEPTION: /* 0x0d */
619/* File: armv5te/OP_MOVE_EXCEPTION.S */
620    /* move-exception vAA */
621    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
622    mov     r2, rINST, lsr #8           @ r2<- AA
623    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
624    mov     r1, #0                      @ r1<- 0
625    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
626    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
627    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
628    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
629    GOTO_OPCODE(ip)                     @ jump to next instruction
630
631
632/* ------------------------------ */
633    .balign 64
634.L_OP_RETURN_VOID: /* 0x0e */
635/* File: armv5te/OP_RETURN_VOID.S */
636    b       common_returnFromMethod
637
638
639/* ------------------------------ */
640    .balign 64
641.L_OP_RETURN: /* 0x0f */
642/* File: armv5te/OP_RETURN.S */
643    /*
644     * Return a 32-bit value.  Copies the return value into the "glue"
645     * structure, then jumps to the return handler.
646     *
647     * for: return, return-object
648     */
649    /* op vAA */
650    mov     r2, rINST, lsr #8           @ r2<- AA
651    GET_VREG(r0, r2)                    @ r0<- vAA
652    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
653    b       common_returnFromMethod
654
655
656/* ------------------------------ */
657    .balign 64
658.L_OP_RETURN_WIDE: /* 0x10 */
659/* File: armv5te/OP_RETURN_WIDE.S */
660    /*
661     * Return a 64-bit value.  Copies the return value into the "glue"
662     * structure, then jumps to the return handler.
663     */
664    /* return-wide vAA */
665    mov     r2, rINST, lsr #8           @ r2<- AA
666    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
667    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
668    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
669    stmia   r3, {r0-r1}                 @ retval<- r0/r1
670    b       common_returnFromMethod
671
672
673/* ------------------------------ */
674    .balign 64
675.L_OP_RETURN_OBJECT: /* 0x11 */
676/* File: armv5te/OP_RETURN_OBJECT.S */
677/* File: armv5te/OP_RETURN.S */
678    /*
679     * Return a 32-bit value.  Copies the return value into the "glue"
680     * structure, then jumps to the return handler.
681     *
682     * for: return, return-object
683     */
684    /* op vAA */
685    mov     r2, rINST, lsr #8           @ r2<- AA
686    GET_VREG(r0, r2)                    @ r0<- vAA
687    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
688    b       common_returnFromMethod
689
690
691
692/* ------------------------------ */
693    .balign 64
694.L_OP_CONST_4: /* 0x12 */
695/* File: armv5te/OP_CONST_4.S */
696    /* const/4 vA, #+B */
697    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
698    mov     r0, rINST, lsr #8           @ r0<- A+
699    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
700    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
701    and     r0, r0, #15
702    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
703    SET_VREG(r1, r0)                    @ fp[A]<- r1
704    GOTO_OPCODE(ip)                     @ execute next instruction
705
706
707/* ------------------------------ */
708    .balign 64
709.L_OP_CONST_16: /* 0x13 */
710/* File: armv5te/OP_CONST_16.S */
711    /* const/16 vAA, #+BBBB */
712    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
713    mov     r3, rINST, lsr #8           @ r3<- AA
714    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
715    SET_VREG(r0, r3)                    @ vAA<- r0
716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
717    GOTO_OPCODE(ip)                     @ jump to next instruction
718
719
720/* ------------------------------ */
721    .balign 64
722.L_OP_CONST: /* 0x14 */
723/* File: armv5te/OP_CONST.S */
724    /* const vAA, #+BBBBbbbb */
725    mov     r3, rINST, lsr #8           @ r3<- AA
726    FETCH(r0, 1)                        @ r0<- bbbb (low)
727    FETCH(r1, 2)                        @ r1<- BBBB (high)
728    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
729    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
731    SET_VREG(r0, r3)                    @ vAA<- r0
732    GOTO_OPCODE(ip)                     @ jump to next instruction
733
734
735/* ------------------------------ */
736    .balign 64
737.L_OP_CONST_HIGH16: /* 0x15 */
738/* File: armv5te/OP_CONST_HIGH16.S */
739    /* const/high16 vAA, #+BBBB0000 */
740    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
741    mov     r3, rINST, lsr #8           @ r3<- AA
742    mov     r0, r0, lsl #16             @ r0<- BBBB0000
743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744    SET_VREG(r0, r3)                    @ vAA<- r0
745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746    GOTO_OPCODE(ip)                     @ jump to next instruction
747
748
749/* ------------------------------ */
750    .balign 64
751.L_OP_CONST_WIDE_16: /* 0x16 */
752/* File: armv5te/OP_CONST_WIDE_16.S */
753    /* const-wide/16 vAA, #+BBBB */
754    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
755    mov     r3, rINST, lsr #8           @ r3<- AA
756    mov     r1, r0, asr #31             @ r1<- ssssssss
757    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
758    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
760    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
761    GOTO_OPCODE(ip)                     @ jump to next instruction
762
763
764/* ------------------------------ */
765    .balign 64
766.L_OP_CONST_WIDE_32: /* 0x17 */
767/* File: armv5te/OP_CONST_WIDE_32.S */
768    /* const-wide/32 vAA, #+BBBBbbbb */
769    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
770    mov     r3, rINST, lsr #8           @ r3<- AA
771    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
772    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
773    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
774    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
775    mov     r1, r0, asr #31             @ r1<- ssssssss
776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
777    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
778    GOTO_OPCODE(ip)                     @ jump to next instruction
779
780
781/* ------------------------------ */
782    .balign 64
783.L_OP_CONST_WIDE: /* 0x18 */
784/* File: armv5te/OP_CONST_WIDE.S */
785    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
786    FETCH(r0, 1)                        @ r0<- bbbb (low)
787    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
788    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
789    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
790    FETCH(r3, 4)                        @ r3<- HHHH (high)
791    mov     r9, rINST, lsr #8           @ r9<- AA
792    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
793    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
794    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
796    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
797    GOTO_OPCODE(ip)                     @ jump to next instruction
798
799
800/* ------------------------------ */
801    .balign 64
802.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
803/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
804    /* const-wide/high16 vAA, #+BBBB000000000000 */
805    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
806    mov     r3, rINST, lsr #8           @ r3<- AA
807    mov     r0, #0                      @ r0<- 00000000
808    mov     r1, r1, lsl #16             @ r1<- BBBB0000
809    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
810    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
812    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
813    GOTO_OPCODE(ip)                     @ jump to next instruction
814
815
816/* ------------------------------ */
817    .balign 64
818.L_OP_CONST_STRING: /* 0x1a */
819/* File: armv5te/OP_CONST_STRING.S */
820    /* const/string vAA, String@BBBB */
821    FETCH(r1, 1)                        @ r1<- BBBB
822    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
823    mov     r9, rINST, lsr #8           @ r9<- AA
824    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
825    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
826    cmp     r0, #0                      @ not yet resolved?
827    beq     .LOP_CONST_STRING_resolve
828    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
830    SET_VREG(r0, r9)                    @ vAA<- r0
831    GOTO_OPCODE(ip)                     @ jump to next instruction
832
833/* ------------------------------ */
834    .balign 64
835.L_OP_CONST_STRING_JUMBO: /* 0x1b */
836/* File: armv5te/OP_CONST_STRING_JUMBO.S */
837    /* const/string vAA, String@BBBBBBBB */
838    FETCH(r0, 1)                        @ r0<- bbbb (low)
839    FETCH(r1, 2)                        @ r1<- BBBB (high)
840    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
841    mov     r9, rINST, lsr #8           @ r9<- AA
842    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
843    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
844    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
845    cmp     r0, #0
846    beq     .LOP_CONST_STRING_JUMBO_resolve
847    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
849    SET_VREG(r0, r9)                    @ vAA<- r0
850    GOTO_OPCODE(ip)                     @ jump to next instruction
851
852/* ------------------------------ */
853    .balign 64
854.L_OP_CONST_CLASS: /* 0x1c */
855/* File: armv5te/OP_CONST_CLASS.S */
856    /* const/class vAA, Class@BBBB */
857    FETCH(r1, 1)                        @ r1<- BBBB
858    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
859    mov     r9, rINST, lsr #8           @ r9<- AA
860    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
861    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
862    cmp     r0, #0                      @ not yet resolved?
863    beq     .LOP_CONST_CLASS_resolve
864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
866    SET_VREG(r0, r9)                    @ vAA<- r0
867    GOTO_OPCODE(ip)                     @ jump to next instruction
868
869/* ------------------------------ */
870    .balign 64
871.L_OP_MONITOR_ENTER: /* 0x1d */
872/* File: armv5te/OP_MONITOR_ENTER.S */
873    /*
874     * Synchronize on an object.
875     */
876    /* monitor-enter vAA */
877    mov     r2, rINST, lsr #8           @ r2<- AA
878    GET_VREG(r1, r2)                    @ r1<- vAA (object)
879    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
880    cmp     r1, #0                      @ null object?
881    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
882    beq     common_errNullObject        @ null object, throw an exception
883    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
884    bl      dvmLockObject               @ call(self, obj)
885#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
886    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
887    ldr     r1, [r0, #offThread_exception] @ check for exception
888    cmp     r1, #0
889    bne     common_exceptionThrown      @ exception raised, bail out
890#endif
891    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
892    GOTO_OPCODE(ip)                     @ jump to next instruction
893
894
895/* ------------------------------ */
896    .balign 64
897.L_OP_MONITOR_EXIT: /* 0x1e */
898/* File: armv5te/OP_MONITOR_EXIT.S */
899    /*
900     * Unlock an object.
901     *
902     * Exceptions that occur when unlocking a monitor need to appear as
903     * if they happened at the following instruction.  See the Dalvik
904     * instruction spec.
905     */
906    /* monitor-exit vAA */
907    mov     r2, rINST, lsr #8           @ r2<- AA
908    EXPORT_PC()                         @ before fetch: export the PC
909    GET_VREG(r1, r2)                    @ r1<- vAA (object)
910    cmp     r1, #0                      @ null object?
911    beq     common_errNullObject        @ yes
912    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
913    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
914    cmp     r0, #0                      @ failed?
915    beq     common_exceptionThrown      @ yes, exception is pending
916    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
918    GOTO_OPCODE(ip)                     @ jump to next instruction
919
920
921/* ------------------------------ */
922    .balign 64
923.L_OP_CHECK_CAST: /* 0x1f */
924/* File: armv5te/OP_CHECK_CAST.S */
925    /*
926     * Check to see if a cast from one class to another is allowed.
927     */
928    /* check-cast vAA, class@BBBB */
929    mov     r3, rINST, lsr #8           @ r3<- AA
930    FETCH(r2, 1)                        @ r2<- BBBB
931    GET_VREG(r9, r3)                    @ r9<- object
932    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
933    cmp     r9, #0                      @ is object null?
934    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
935    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
936    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
937    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
938    cmp     r1, #0                      @ have we resolved this before?
939    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
940.LOP_CHECK_CAST_resolved:
941    cmp     r0, r1                      @ same class (trivial success)?
942    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
943.LOP_CHECK_CAST_okay:
944    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
946    GOTO_OPCODE(ip)                     @ jump to next instruction
947
948/* ------------------------------ */
949    .balign 64
950.L_OP_INSTANCE_OF: /* 0x20 */
951/* File: armv5te/OP_INSTANCE_OF.S */
952    /*
953     * Check to see if an object reference is an instance of a class.
954     *
955     * Most common situation is a non-null object, being compared against
956     * an already-resolved class.
957     */
958    /* instance-of vA, vB, class@CCCC */
959    mov     r3, rINST, lsr #12          @ r3<- B
960    mov     r9, rINST, lsr #8           @ r9<- A+
961    GET_VREG(r0, r3)                    @ r0<- vB (object)
962    and     r9, r9, #15                 @ r9<- A
963    cmp     r0, #0                      @ is object null?
964    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
965    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
966    FETCH(r3, 1)                        @ r3<- CCCC
967    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
968    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
969    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
970    cmp     r1, #0                      @ have we resolved this before?
971    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
972.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
973    cmp     r0, r1                      @ same class (trivial success)?
974    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
975    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
976
977/* ------------------------------ */
978    .balign 64
979.L_OP_ARRAY_LENGTH: /* 0x21 */
980/* File: armv5te/OP_ARRAY_LENGTH.S */
981    /*
982     * Return the length of an array.
983     */
984    mov     r1, rINST, lsr #12          @ r1<- B
985    mov     r2, rINST, lsr #8           @ r2<- A+
986    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
987    and     r2, r2, #15                 @ r2<- A
988    cmp     r0, #0                      @ is object null?
989    beq     common_errNullObject        @ yup, fail
990    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
991    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
993    SET_VREG(r3, r2)                    @ vB<- length
994    GOTO_OPCODE(ip)                     @ jump to next instruction
995
996
997/* ------------------------------ */
998    .balign 64
999.L_OP_NEW_INSTANCE: /* 0x22 */
1000/* File: armv5te/OP_NEW_INSTANCE.S */
1001    /*
1002     * Create a new instance of a class.
1003     */
1004    /* new-instance vAA, class@BBBB */
1005    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1006    FETCH(r1, 1)                        @ r1<- BBBB
1007    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1008    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1009    EXPORT_PC()                         @ req'd for init, resolve, alloc
1010    cmp     r0, #0                      @ already resolved?
1011    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1012.LOP_NEW_INSTANCE_resolved:   @ r0=class
1013    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1014    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1015    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1016.LOP_NEW_INSTANCE_initialized: @ r0=class
1017    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1018    bl      dvmAllocObject              @ r0<- new object
1019    b       .LOP_NEW_INSTANCE_finish          @ continue
1020
1021/* ------------------------------ */
1022    .balign 64
1023.L_OP_NEW_ARRAY: /* 0x23 */
1024/* File: armv5te/OP_NEW_ARRAY.S */
1025    /*
1026     * Allocate an array of objects, specified with the array class
1027     * and a count.
1028     *
1029     * The verifier guarantees that this is an array class, so we don't
1030     * check for it here.
1031     */
1032    /* new-array vA, vB, class@CCCC */
1033    mov     r0, rINST, lsr #12          @ r0<- B
1034    FETCH(r2, 1)                        @ r2<- CCCC
1035    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1036    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1037    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1038    cmp     r1, #0                      @ check length
1039    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1040    bmi     common_errNegativeArraySize @ negative length, bail
1041    cmp     r0, #0                      @ already resolved?
1042    EXPORT_PC()                         @ req'd for resolve, alloc
1043    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1044    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1045
1046/* ------------------------------ */
1047    .balign 64
1048.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1049/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1050    /*
1051     * Create a new array with elements filled from registers.
1052     *
1053     * for: filled-new-array, filled-new-array/range
1054     */
1055    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1056    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1057    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1058    FETCH(r1, 1)                        @ r1<- BBBB
1059    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1060    EXPORT_PC()                         @ need for resolve and alloc
1061    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1062    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1063    cmp     r0, #0                      @ already resolved?
1064    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10658:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1066    mov     r2, #0                      @ r2<- false
1067    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1068    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1069    cmp     r0, #0                      @ got null?
1070    beq     common_exceptionThrown      @ yes, handle exception
1071    b       .LOP_FILLED_NEW_ARRAY_continue
1072
1073/* ------------------------------ */
1074    .balign 64
1075.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1076/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1077/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1078    /*
1079     * Create a new array with elements filled from registers.
1080     *
1081     * for: filled-new-array, filled-new-array/range
1082     */
1083    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1084    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1085    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1086    FETCH(r1, 1)                        @ r1<- BBBB
1087    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1088    EXPORT_PC()                         @ need for resolve and alloc
1089    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1090    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1091    cmp     r0, #0                      @ already resolved?
1092    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10938:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1094    mov     r2, #0                      @ r2<- false
1095    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1096    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1097    cmp     r0, #0                      @ got null?
1098    beq     common_exceptionThrown      @ yes, handle exception
1099    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1100
1101
1102/* ------------------------------ */
1103    .balign 64
1104.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1105/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1106    /* fill-array-data vAA, +BBBBBBBB */
1107    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1108    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1109    mov     r3, rINST, lsr #8           @ r3<- AA
1110    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1111    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1112    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1113    EXPORT_PC();
1114    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1115    cmp     r0, #0                      @ 0 means an exception is thrown
1116    beq     common_exceptionThrown      @ has exception
1117    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1119    GOTO_OPCODE(ip)                     @ jump to next instruction
1120
1121/* ------------------------------ */
1122    .balign 64
1123.L_OP_THROW: /* 0x27 */
1124/* File: armv5te/OP_THROW.S */
1125    /*
1126     * Throw an exception object in the current thread.
1127     */
1128    /* throw vAA */
1129    mov     r2, rINST, lsr #8           @ r2<- AA
1130    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1131    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1132    cmp     r1, #0                      @ null object?
1133    beq     common_errNullObject        @ yes, throw an NPE instead
1134    @ bypass dvmSetException, just store it
1135    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1136    b       common_exceptionThrown
1137
1138
1139/* ------------------------------ */
1140    .balign 64
1141.L_OP_GOTO: /* 0x28 */
1142/* File: armv5te/OP_GOTO.S */
1143    /*
1144     * Unconditional branch, 8-bit offset.
1145     *
1146     * The branch distance is a signed code-unit offset, which we need to
1147     * double to get a byte offset.
1148     */
1149    /* goto +AA */
1150    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1151    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1152    mov     r9, r9, lsl #1              @ r9<- byte offset
1153    bmi     common_backwardBranch       @ backward branch, do periodic checks
1154#if defined(WITH_JIT)
1155    GET_JIT_PROF_TABLE(r0)
1156    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1157    cmp     r0,#0
1158    bne     common_updateProfile
1159    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1160    GOTO_OPCODE(ip)                     @ jump to next instruction
1161#else
1162    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1163    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1164    GOTO_OPCODE(ip)                     @ jump to next instruction
1165#endif
1166
1167/* ------------------------------ */
1168    .balign 64
1169.L_OP_GOTO_16: /* 0x29 */
1170/* File: armv5te/OP_GOTO_16.S */
1171    /*
1172     * Unconditional branch, 16-bit offset.
1173     *
1174     * The branch distance is a signed code-unit offset, which we need to
1175     * double to get a byte offset.
1176     */
1177    /* goto/16 +AAAA */
1178    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1179    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1180    bmi     common_backwardBranch       @ backward branch, do periodic checks
1181#if defined(WITH_JIT)
1182    GET_JIT_PROF_TABLE(r0)
1183    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1184    cmp     r0,#0
1185    bne     common_updateProfile
1186    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1187    GOTO_OPCODE(ip)                     @ jump to next instruction
1188#else
1189    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1191    GOTO_OPCODE(ip)                     @ jump to next instruction
1192#endif
1193
1194
1195/* ------------------------------ */
1196    .balign 64
1197.L_OP_GOTO_32: /* 0x2a */
1198/* File: armv5te/OP_GOTO_32.S */
1199    /*
1200     * Unconditional branch, 32-bit offset.
1201     *
1202     * The branch distance is a signed code-unit offset, which we need to
1203     * double to get a byte offset.
1204     *
1205     * Unlike most opcodes, this one is allowed to branch to itself, so
1206     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1207     * instruction doesn't affect the V flag, so we need to clear it
1208     * explicitly.
1209     */
1210    /* goto/32 +AAAAAAAA */
1211    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1212    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1213    cmp     ip, ip                      @ (clear V flag during stall)
1214    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1215    mov     r9, r0, asl #1              @ r9<- byte offset
1216    ble     common_backwardBranch       @ backward branch, do periodic checks
1217#if defined(WITH_JIT)
1218    GET_JIT_PROF_TABLE(r0)
1219    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1220    cmp     r0,#0
1221    bne     common_updateProfile
1222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1223    GOTO_OPCODE(ip)                     @ jump to next instruction
1224#else
1225    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1226    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1227    GOTO_OPCODE(ip)                     @ jump to next instruction
1228#endif
1229
1230/* ------------------------------ */
1231    .balign 64
1232.L_OP_PACKED_SWITCH: /* 0x2b */
1233/* File: armv5te/OP_PACKED_SWITCH.S */
1234    /*
1235     * Handle a packed-switch or sparse-switch instruction.  In both cases
1236     * we decode it and hand it off to a helper function.
1237     *
1238     * We don't really expect backward branches in a switch statement, but
1239     * they're perfectly legal, so we check for them here.
1240     *
1241     * for: packed-switch, sparse-switch
1242     */
1243    /* op vAA, +BBBB */
1244    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1245    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1246    mov     r3, rINST, lsr #8           @ r3<- AA
1247    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1248    GET_VREG(r1, r3)                    @ r1<- vAA
1249    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1250    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1251    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1252    bmi     common_backwardBranch       @ backward branch, do periodic checks
1253    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1254#if defined(WITH_JIT)
1255    GET_JIT_PROF_TABLE(r0)
1256    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1257    cmp     r0,#0
1258    bne     common_updateProfile
1259    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1260    GOTO_OPCODE(ip)                     @ jump to next instruction
1261#else
1262    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1264    GOTO_OPCODE(ip)                     @ jump to next instruction
1265#endif
1266
1267
1268/* ------------------------------ */
1269    .balign 64
1270.L_OP_SPARSE_SWITCH: /* 0x2c */
1271/* File: armv5te/OP_SPARSE_SWITCH.S */
1272/* File: armv5te/OP_PACKED_SWITCH.S */
1273    /*
1274     * Handle a packed-switch or sparse-switch instruction.  In both cases
1275     * we decode it and hand it off to a helper function.
1276     *
1277     * We don't really expect backward branches in a switch statement, but
1278     * they're perfectly legal, so we check for them here.
1279     *
1280     * for: packed-switch, sparse-switch
1281     */
1282    /* op vAA, +BBBB */
1283    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1284    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1285    mov     r3, rINST, lsr #8           @ r3<- AA
1286    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1287    GET_VREG(r1, r3)                    @ r1<- vAA
1288    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1289    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1290    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1291    bmi     common_backwardBranch       @ backward branch, do periodic checks
1292    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1293#if defined(WITH_JIT)
1294    GET_JIT_PROF_TABLE(r0)
1295    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1296    cmp     r0,#0
1297    bne     common_updateProfile
1298    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1299    GOTO_OPCODE(ip)                     @ jump to next instruction
1300#else
1301    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1303    GOTO_OPCODE(ip)                     @ jump to next instruction
1304#endif
1305
1306
1307
1308/* ------------------------------ */
1309    .balign 64
1310.L_OP_CMPL_FLOAT: /* 0x2d */
1311/* File: arm-vfp/OP_CMPL_FLOAT.S */
1312    /*
1313     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1314     * destination register based on the results of the comparison.
1315     *
1316     * int compare(x, y) {
1317     *     if (x == y) {
1318     *         return 0;
1319     *     } else if (x > y) {
1320     *         return 1;
1321     *     } else if (x < y) {
1322     *         return -1;
1323     *     } else {
1324     *         return -1;
1325     *     }
1326     * }
1327     */
1328    /* op vAA, vBB, vCC */
1329    FETCH(r0, 1)                        @ r0<- CCBB
1330    mov     r9, rINST, lsr #8           @ r9<- AA
1331    and     r2, r0, #255                @ r2<- BB
1332    mov     r3, r0, lsr #8              @ r3<- CC
1333    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1334    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1335    flds    s0, [r2]                    @ s0<- vBB
1336    flds    s1, [r3]                    @ s1<- vCC
1337    fcmpes  s0, s1                      @ compare (vBB, vCC)
1338    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1339    mvn     r0, #0                      @ r0<- -1 (default)
1340    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1341    fmstat                              @ export status flags
1342    movgt   r0, #1                      @ (greater than) r1<- 1
1343    moveq   r0, #0                      @ (equal) r1<- 0
1344    b       .LOP_CMPL_FLOAT_finish          @ argh
1345
1346
1347/* ------------------------------ */
1348    .balign 64
1349.L_OP_CMPG_FLOAT: /* 0x2e */
1350/* File: arm-vfp/OP_CMPG_FLOAT.S */
1351    /*
1352     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1353     * destination register based on the results of the comparison.
1354     *
1355     * int compare(x, y) {
1356     *     if (x == y) {
1357     *         return 0;
1358     *     } else if (x < y) {
1359     *         return -1;
1360     *     } else if (x > y) {
1361     *         return 1;
1362     *     } else {
1363     *         return 1;
1364     *     }
1365     * }
1366     */
1367    /* op vAA, vBB, vCC */
1368    FETCH(r0, 1)                        @ r0<- CCBB
1369    mov     r9, rINST, lsr #8           @ r9<- AA
1370    and     r2, r0, #255                @ r2<- BB
1371    mov     r3, r0, lsr #8              @ r3<- CC
1372    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1373    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1374    flds    s0, [r2]                    @ s0<- vBB
1375    flds    s1, [r3]                    @ s1<- vCC
1376    fcmpes  s0, s1                      @ compare (vBB, vCC)
1377    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1378    mov     r0, #1                      @ r0<- 1 (default)
1379    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1380    fmstat                              @ export status flags
1381    mvnmi   r0, #0                      @ (less than) r1<- -1
1382    moveq   r0, #0                      @ (equal) r1<- 0
1383    b       .LOP_CMPG_FLOAT_finish          @ argh
1384
1385
1386/* ------------------------------ */
1387    .balign 64
1388.L_OP_CMPL_DOUBLE: /* 0x2f */
1389/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1390    /*
1391     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1392     * destination register based on the results of the comparison.
1393     *
1394     * int compare(x, y) {
1395     *     if (x == y) {
1396     *         return 0;
1397     *     } else if (x > y) {
1398     *         return 1;
1399     *     } else if (x < y) {
1400     *         return -1;
1401     *     } else {
1402     *         return -1;
1403     *     }
1404     * }
1405     */
1406    /* op vAA, vBB, vCC */
1407    FETCH(r0, 1)                        @ r0<- CCBB
1408    mov     r9, rINST, lsr #8           @ r9<- AA
1409    and     r2, r0, #255                @ r2<- BB
1410    mov     r3, r0, lsr #8              @ r3<- CC
1411    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1412    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1413    fldd    d0, [r2]                    @ d0<- vBB
1414    fldd    d1, [r3]                    @ d1<- vCC
1415    fcmped  d0, d1                      @ compare (vBB, vCC)
1416    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1417    mvn     r0, #0                      @ r0<- -1 (default)
1418    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1419    fmstat                              @ export status flags
1420    movgt   r0, #1                      @ (greater than) r1<- 1
1421    moveq   r0, #0                      @ (equal) r1<- 0
1422    b       .LOP_CMPL_DOUBLE_finish          @ argh
1423
1424
1425/* ------------------------------ */
1426    .balign 64
1427.L_OP_CMPG_DOUBLE: /* 0x30 */
1428/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1429    /*
1430     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1431     * destination register based on the results of the comparison.
1432     *
1433     * int compare(x, y) {
1434     *     if (x == y) {
1435     *         return 0;
1436     *     } else if (x < y) {
1437     *         return -1;
1438     *     } else if (x > y) {
1439     *         return 1;
1440     *     } else {
1441     *         return 1;
1442     *     }
1443     * }
1444     */
1445    /* op vAA, vBB, vCC */
1446    FETCH(r0, 1)                        @ r0<- CCBB
1447    mov     r9, rINST, lsr #8           @ r9<- AA
1448    and     r2, r0, #255                @ r2<- BB
1449    mov     r3, r0, lsr #8              @ r3<- CC
1450    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1451    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1452    fldd    d0, [r2]                    @ d0<- vBB
1453    fldd    d1, [r3]                    @ d1<- vCC
1454    fcmped  d0, d1                      @ compare (vBB, vCC)
1455    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1456    mov     r0, #1                      @ r0<- 1 (default)
1457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1458    fmstat                              @ export status flags
1459    mvnmi   r0, #0                      @ (less than) r1<- -1
1460    moveq   r0, #0                      @ (equal) r1<- 0
1461    b       .LOP_CMPG_DOUBLE_finish          @ argh
1462
1463
1464/* ------------------------------ */
1465    .balign 64
1466.L_OP_CMP_LONG: /* 0x31 */
1467/* File: armv5te/OP_CMP_LONG.S */
1468    /*
1469     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1470     * register based on the results of the comparison.
1471     *
1472     * We load the full values with LDM, but in practice many values could
1473     * be resolved by only looking at the high word.  This could be made
1474     * faster or slower by splitting the LDM into a pair of LDRs.
1475     *
1476     * If we just wanted to set condition flags, we could do this:
1477     *  subs    ip, r0, r2
1478     *  sbcs    ip, r1, r3
1479     *  subeqs  ip, r0, r2
1480     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1481     * integer value, which we can do with 2 conditional mov/mvn instructions
1482     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1483     * us a constant 5-cycle path plus a branch at the end to the
1484     * instruction epilogue code.  The multi-compare approach below needs
1485     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1486     * in the worst case (the 64-bit values are equal).
1487     */
1488    /* cmp-long vAA, vBB, vCC */
1489    FETCH(r0, 1)                        @ r0<- CCBB
1490    mov     r9, rINST, lsr #8           @ r9<- AA
1491    and     r2, r0, #255                @ r2<- BB
1492    mov     r3, r0, lsr #8              @ r3<- CC
1493    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1494    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1495    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1496    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1497    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1498    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1499    bgt     .LOP_CMP_LONG_greater
1500    subs    r1, r0, r2                  @ r1<- r0 - r2
1501    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1502    bne     .LOP_CMP_LONG_less
1503    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1504
1505/* ------------------------------ */
1506    .balign 64
1507.L_OP_IF_EQ: /* 0x32 */
1508/* File: armv5te/OP_IF_EQ.S */
1509/* File: armv5te/bincmp.S */
1510    /*
1511     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1512     * fragment that specifies the *reverse* comparison to perform, e.g.
1513     * for "if-le" you would use "gt".
1514     *
1515     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1516     */
1517    /* if-cmp vA, vB, +CCCC */
1518    mov     r0, rINST, lsr #8           @ r0<- A+
1519    mov     r1, rINST, lsr #12          @ r1<- B
1520    and     r0, r0, #15
1521    GET_VREG(r3, r1)                    @ r3<- vB
1522    GET_VREG(r2, r0)                    @ r2<- vA
1523    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1524    cmp     r2, r3                      @ compare (vA, vB)
1525    bne  1f                      @ branch to 1 if comparison failed
1526    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1527    movs    r9, r9, asl #1              @ convert to bytes, check sign
1528    bmi     common_backwardBranch       @ yes, do periodic checks
15291:
1530#if defined(WITH_JIT)
1531    GET_JIT_PROF_TABLE(r0)
1532    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1533    b        common_testUpdateProfile
1534#else
1535    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1537    GOTO_OPCODE(ip)                     @ jump to next instruction
1538#endif
1539
1540
1541
1542/* ------------------------------ */
1543    .balign 64
1544.L_OP_IF_NE: /* 0x33 */
1545/* File: armv5te/OP_IF_NE.S */
1546/* File: armv5te/bincmp.S */
1547    /*
1548     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1549     * fragment that specifies the *reverse* comparison to perform, e.g.
1550     * for "if-le" you would use "gt".
1551     *
1552     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1553     */
1554    /* if-cmp vA, vB, +CCCC */
1555    mov     r0, rINST, lsr #8           @ r0<- A+
1556    mov     r1, rINST, lsr #12          @ r1<- B
1557    and     r0, r0, #15
1558    GET_VREG(r3, r1)                    @ r3<- vB
1559    GET_VREG(r2, r0)                    @ r2<- vA
1560    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1561    cmp     r2, r3                      @ compare (vA, vB)
1562    beq  1f                      @ branch to 1 if comparison failed
1563    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1564    movs    r9, r9, asl #1              @ convert to bytes, check sign
1565    bmi     common_backwardBranch       @ yes, do periodic checks
15661:
1567#if defined(WITH_JIT)
1568    GET_JIT_PROF_TABLE(r0)
1569    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1570    b        common_testUpdateProfile
1571#else
1572    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1574    GOTO_OPCODE(ip)                     @ jump to next instruction
1575#endif
1576
1577
1578
1579/* ------------------------------ */
1580    .balign 64
1581.L_OP_IF_LT: /* 0x34 */
1582/* File: armv5te/OP_IF_LT.S */
1583/* File: armv5te/bincmp.S */
1584    /*
1585     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1586     * fragment that specifies the *reverse* comparison to perform, e.g.
1587     * for "if-le" you would use "gt".
1588     *
1589     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1590     */
1591    /* if-cmp vA, vB, +CCCC */
1592    mov     r0, rINST, lsr #8           @ r0<- A+
1593    mov     r1, rINST, lsr #12          @ r1<- B
1594    and     r0, r0, #15
1595    GET_VREG(r3, r1)                    @ r3<- vB
1596    GET_VREG(r2, r0)                    @ r2<- vA
1597    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1598    cmp     r2, r3                      @ compare (vA, vB)
1599    bge  1f                      @ branch to 1 if comparison failed
1600    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1601    movs    r9, r9, asl #1              @ convert to bytes, check sign
1602    bmi     common_backwardBranch       @ yes, do periodic checks
16031:
1604#if defined(WITH_JIT)
1605    GET_JIT_PROF_TABLE(r0)
1606    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1607    b        common_testUpdateProfile
1608#else
1609    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1610    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1611    GOTO_OPCODE(ip)                     @ jump to next instruction
1612#endif
1613
1614
1615
1616/* ------------------------------ */
1617    .balign 64
1618.L_OP_IF_GE: /* 0x35 */
1619/* File: armv5te/OP_IF_GE.S */
1620/* File: armv5te/bincmp.S */
1621    /*
1622     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1623     * fragment that specifies the *reverse* comparison to perform, e.g.
1624     * for "if-le" you would use "gt".
1625     *
1626     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1627     */
1628    /* if-cmp vA, vB, +CCCC */
1629    mov     r0, rINST, lsr #8           @ r0<- A+
1630    mov     r1, rINST, lsr #12          @ r1<- B
1631    and     r0, r0, #15
1632    GET_VREG(r3, r1)                    @ r3<- vB
1633    GET_VREG(r2, r0)                    @ r2<- vA
1634    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1635    cmp     r2, r3                      @ compare (vA, vB)
1636    blt  1f                      @ branch to 1 if comparison failed
1637    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1638    movs    r9, r9, asl #1              @ convert to bytes, check sign
1639    bmi     common_backwardBranch       @ yes, do periodic checks
16401:
1641#if defined(WITH_JIT)
1642    GET_JIT_PROF_TABLE(r0)
1643    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1644    b        common_testUpdateProfile
1645#else
1646    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1647    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1648    GOTO_OPCODE(ip)                     @ jump to next instruction
1649#endif
1650
1651
1652
1653/* ------------------------------ */
1654    .balign 64
1655.L_OP_IF_GT: /* 0x36 */
1656/* File: armv5te/OP_IF_GT.S */
1657/* File: armv5te/bincmp.S */
1658    /*
1659     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1660     * fragment that specifies the *reverse* comparison to perform, e.g.
1661     * for "if-le" you would use "gt".
1662     *
1663     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1664     */
1665    /* if-cmp vA, vB, +CCCC */
1666    mov     r0, rINST, lsr #8           @ r0<- A+
1667    mov     r1, rINST, lsr #12          @ r1<- B
1668    and     r0, r0, #15
1669    GET_VREG(r3, r1)                    @ r3<- vB
1670    GET_VREG(r2, r0)                    @ r2<- vA
1671    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1672    cmp     r2, r3                      @ compare (vA, vB)
1673    ble  1f                      @ branch to 1 if comparison failed
1674    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1675    movs    r9, r9, asl #1              @ convert to bytes, check sign
1676    bmi     common_backwardBranch       @ yes, do periodic checks
16771:
1678#if defined(WITH_JIT)
1679    GET_JIT_PROF_TABLE(r0)
1680    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1681    b        common_testUpdateProfile
1682#else
1683    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1684    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1685    GOTO_OPCODE(ip)                     @ jump to next instruction
1686#endif
1687
1688
1689
1690/* ------------------------------ */
1691    .balign 64
1692.L_OP_IF_LE: /* 0x37 */
1693/* File: armv5te/OP_IF_LE.S */
1694/* File: armv5te/bincmp.S */
1695    /*
1696     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1697     * fragment that specifies the *reverse* comparison to perform, e.g.
1698     * for "if-le" you would use "gt".
1699     *
1700     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1701     */
1702    /* if-cmp vA, vB, +CCCC */
1703    mov     r0, rINST, lsr #8           @ r0<- A+
1704    mov     r1, rINST, lsr #12          @ r1<- B
1705    and     r0, r0, #15
1706    GET_VREG(r3, r1)                    @ r3<- vB
1707    GET_VREG(r2, r0)                    @ r2<- vA
1708    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1709    cmp     r2, r3                      @ compare (vA, vB)
1710    bgt  1f                      @ branch to 1 if comparison failed
1711    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1712    movs    r9, r9, asl #1              @ convert to bytes, check sign
1713    bmi     common_backwardBranch       @ yes, do periodic checks
17141:
1715#if defined(WITH_JIT)
1716    GET_JIT_PROF_TABLE(r0)
1717    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1718    b        common_testUpdateProfile
1719#else
1720    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1722    GOTO_OPCODE(ip)                     @ jump to next instruction
1723#endif
1724
1725
1726
1727/* ------------------------------ */
1728    .balign 64
1729.L_OP_IF_EQZ: /* 0x38 */
1730/* File: armv5te/OP_IF_EQZ.S */
1731/* File: armv5te/zcmp.S */
1732    /*
1733     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1734     * fragment that specifies the *reverse* comparison to perform, e.g.
1735     * for "if-le" you would use "gt".
1736     *
1737     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1738     */
1739    /* if-cmp vAA, +BBBB */
1740    mov     r0, rINST, lsr #8           @ r0<- AA
1741    GET_VREG(r2, r0)                    @ r2<- vAA
1742    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1743    cmp     r2, #0                      @ compare (vA, 0)
1744    bne  1f                      @ branch to 1 if comparison failed
1745    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1746    movs    r9, r9, asl #1              @ convert to bytes, check sign
1747    bmi     common_backwardBranch       @ backward branch, do periodic checks
17481:
1749#if defined(WITH_JIT)
1750    GET_JIT_PROF_TABLE(r0)
1751    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1752    cmp     r0,#0
1753    bne     common_updateProfile
1754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1755    GOTO_OPCODE(ip)                     @ jump to next instruction
1756#else
1757    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1758    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1759    GOTO_OPCODE(ip)                     @ jump to next instruction
1760#endif
1761
1762
1763
1764/* ------------------------------ */
1765    .balign 64
1766.L_OP_IF_NEZ: /* 0x39 */
1767/* File: armv5te/OP_IF_NEZ.S */
1768/* File: armv5te/zcmp.S */
1769    /*
1770     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1771     * fragment that specifies the *reverse* comparison to perform, e.g.
1772     * for "if-le" you would use "gt".
1773     *
1774     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1775     */
1776    /* if-cmp vAA, +BBBB */
1777    mov     r0, rINST, lsr #8           @ r0<- AA
1778    GET_VREG(r2, r0)                    @ r2<- vAA
1779    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1780    cmp     r2, #0                      @ compare (vA, 0)
1781    beq  1f                      @ branch to 1 if comparison failed
1782    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1783    movs    r9, r9, asl #1              @ convert to bytes, check sign
1784    bmi     common_backwardBranch       @ backward branch, do periodic checks
17851:
1786#if defined(WITH_JIT)
1787    GET_JIT_PROF_TABLE(r0)
1788    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1789    cmp     r0,#0
1790    bne     common_updateProfile
1791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1792    GOTO_OPCODE(ip)                     @ jump to next instruction
1793#else
1794    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1796    GOTO_OPCODE(ip)                     @ jump to next instruction
1797#endif
1798
1799
1800
1801/* ------------------------------ */
1802    .balign 64
1803.L_OP_IF_LTZ: /* 0x3a */
1804/* File: armv5te/OP_IF_LTZ.S */
1805/* File: armv5te/zcmp.S */
1806    /*
1807     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1808     * fragment that specifies the *reverse* comparison to perform, e.g.
1809     * for "if-le" you would use "gt".
1810     *
1811     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1812     */
1813    /* if-cmp vAA, +BBBB */
1814    mov     r0, rINST, lsr #8           @ r0<- AA
1815    GET_VREG(r2, r0)                    @ r2<- vAA
1816    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1817    cmp     r2, #0                      @ compare (vA, 0)
1818    bge  1f                      @ branch to 1 if comparison failed
1819    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1820    movs    r9, r9, asl #1              @ convert to bytes, check sign
1821    bmi     common_backwardBranch       @ backward branch, do periodic checks
18221:
1823#if defined(WITH_JIT)
1824    GET_JIT_PROF_TABLE(r0)
1825    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1826    cmp     r0,#0
1827    bne     common_updateProfile
1828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829    GOTO_OPCODE(ip)                     @ jump to next instruction
1830#else
1831    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1833    GOTO_OPCODE(ip)                     @ jump to next instruction
1834#endif
1835
1836
1837
1838/* ------------------------------ */
1839    .balign 64
1840.L_OP_IF_GEZ: /* 0x3b */
1841/* File: armv5te/OP_IF_GEZ.S */
1842/* File: armv5te/zcmp.S */
1843    /*
1844     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1845     * fragment that specifies the *reverse* comparison to perform, e.g.
1846     * for "if-le" you would use "gt".
1847     *
1848     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1849     */
1850    /* if-cmp vAA, +BBBB */
1851    mov     r0, rINST, lsr #8           @ r0<- AA
1852    GET_VREG(r2, r0)                    @ r2<- vAA
1853    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1854    cmp     r2, #0                      @ compare (vA, 0)
1855    blt  1f                      @ branch to 1 if comparison failed
1856    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1857    movs    r9, r9, asl #1              @ convert to bytes, check sign
1858    bmi     common_backwardBranch       @ backward branch, do periodic checks
18591:
1860#if defined(WITH_JIT)
1861    GET_JIT_PROF_TABLE(r0)
1862    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1863    cmp     r0,#0
1864    bne     common_updateProfile
1865    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1866    GOTO_OPCODE(ip)                     @ jump to next instruction
1867#else
1868    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1870    GOTO_OPCODE(ip)                     @ jump to next instruction
1871#endif
1872
1873
1874
1875/* ------------------------------ */
1876    .balign 64
1877.L_OP_IF_GTZ: /* 0x3c */
1878/* File: armv5te/OP_IF_GTZ.S */
1879/* File: armv5te/zcmp.S */
1880    /*
1881     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1882     * fragment that specifies the *reverse* comparison to perform, e.g.
1883     * for "if-le" you would use "gt".
1884     *
1885     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1886     */
1887    /* if-cmp vAA, +BBBB */
1888    mov     r0, rINST, lsr #8           @ r0<- AA
1889    GET_VREG(r2, r0)                    @ r2<- vAA
1890    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1891    cmp     r2, #0                      @ compare (vA, 0)
1892    ble  1f                      @ branch to 1 if comparison failed
1893    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1894    movs    r9, r9, asl #1              @ convert to bytes, check sign
1895    bmi     common_backwardBranch       @ backward branch, do periodic checks
18961:
1897#if defined(WITH_JIT)
1898    GET_JIT_PROF_TABLE(r0)
1899    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1900    cmp     r0,#0
1901    bne     common_updateProfile
1902    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1903    GOTO_OPCODE(ip)                     @ jump to next instruction
1904#else
1905    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1907    GOTO_OPCODE(ip)                     @ jump to next instruction
1908#endif
1909
1910
1911
1912/* ------------------------------ */
1913    .balign 64
1914.L_OP_IF_LEZ: /* 0x3d */
1915/* File: armv5te/OP_IF_LEZ.S */
1916/* File: armv5te/zcmp.S */
1917    /*
1918     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1919     * fragment that specifies the *reverse* comparison to perform, e.g.
1920     * for "if-le" you would use "gt".
1921     *
1922     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1923     */
1924    /* if-cmp vAA, +BBBB */
1925    mov     r0, rINST, lsr #8           @ r0<- AA
1926    GET_VREG(r2, r0)                    @ r2<- vAA
1927    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1928    cmp     r2, #0                      @ compare (vA, 0)
1929    bgt  1f                      @ branch to 1 if comparison failed
1930    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1931    movs    r9, r9, asl #1              @ convert to bytes, check sign
1932    bmi     common_backwardBranch       @ backward branch, do periodic checks
19331:
1934#if defined(WITH_JIT)
1935    GET_JIT_PROF_TABLE(r0)
1936    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1937    cmp     r0,#0
1938    bne     common_updateProfile
1939    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1940    GOTO_OPCODE(ip)                     @ jump to next instruction
1941#else
1942    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1943    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1944    GOTO_OPCODE(ip)                     @ jump to next instruction
1945#endif
1946
1947
1948
1949/* ------------------------------ */
1950    .balign 64
1951.L_OP_UNUSED_3E: /* 0x3e */
1952/* File: armv5te/OP_UNUSED_3E.S */
1953/* File: armv5te/unused.S */
1954    bl      common_abort
1955
1956
1957
1958/* ------------------------------ */
1959    .balign 64
1960.L_OP_UNUSED_3F: /* 0x3f */
1961/* File: armv5te/OP_UNUSED_3F.S */
1962/* File: armv5te/unused.S */
1963    bl      common_abort
1964
1965
1966
1967/* ------------------------------ */
1968    .balign 64
1969.L_OP_UNUSED_40: /* 0x40 */
1970/* File: armv5te/OP_UNUSED_40.S */
1971/* File: armv5te/unused.S */
1972    bl      common_abort
1973
1974
1975
1976/* ------------------------------ */
1977    .balign 64
1978.L_OP_UNUSED_41: /* 0x41 */
1979/* File: armv5te/OP_UNUSED_41.S */
1980/* File: armv5te/unused.S */
1981    bl      common_abort
1982
1983
1984
1985/* ------------------------------ */
1986    .balign 64
1987.L_OP_UNUSED_42: /* 0x42 */
1988/* File: armv5te/OP_UNUSED_42.S */
1989/* File: armv5te/unused.S */
1990    bl      common_abort
1991
1992
1993
1994/* ------------------------------ */
1995    .balign 64
1996.L_OP_UNUSED_43: /* 0x43 */
1997/* File: armv5te/OP_UNUSED_43.S */
1998/* File: armv5te/unused.S */
1999    bl      common_abort
2000
2001
2002
2003/* ------------------------------ */
2004    .balign 64
2005.L_OP_AGET: /* 0x44 */
2006/* File: armv5te/OP_AGET.S */
2007    /*
2008     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2009     *
2010     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2011     * instructions.  We use a pair of FETCH_Bs instead.
2012     *
2013     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2014     */
2015    /* op vAA, vBB, vCC */
2016    FETCH_B(r2, 1, 0)                   @ r2<- BB
2017    mov     r9, rINST, lsr #8           @ r9<- AA
2018    FETCH_B(r3, 1, 1)                   @ r3<- CC
2019    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2020    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2021    cmp     r0, #0                      @ null array object?
2022    beq     common_errNullObject        @ yes, bail
2023    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2024    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2025    cmp     r1, r3                      @ compare unsigned index, length
2026    bcs     common_errArrayIndex        @ index >= length, bail
2027    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2028    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2030    SET_VREG(r2, r9)                    @ vAA<- r2
2031    GOTO_OPCODE(ip)                     @ jump to next instruction
2032
2033
2034/* ------------------------------ */
2035    .balign 64
2036.L_OP_AGET_WIDE: /* 0x45 */
2037/* File: armv5te/OP_AGET_WIDE.S */
2038    /*
2039     * Array get, 64 bits.  vAA <- vBB[vCC].
2040     *
2041     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2042     */
2043    /* aget-wide vAA, vBB, vCC */
2044    FETCH(r0, 1)                        @ r0<- CCBB
2045    mov     r9, rINST, lsr #8           @ r9<- AA
2046    and     r2, r0, #255                @ r2<- BB
2047    mov     r3, r0, lsr #8              @ r3<- CC
2048    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2049    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2050    cmp     r0, #0                      @ null array object?
2051    beq     common_errNullObject        @ yes, bail
2052    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2053    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2054    cmp     r1, r3                      @ compare unsigned index, length
2055    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2056    b       common_errArrayIndex        @ index >= length, bail
2057    @ May want to swap the order of these two branches depending on how the
2058    @ branch prediction (if any) handles conditional forward branches vs.
2059    @ unconditional forward branches.
2060
2061/* ------------------------------ */
2062    .balign 64
2063.L_OP_AGET_OBJECT: /* 0x46 */
2064/* File: armv5te/OP_AGET_OBJECT.S */
2065/* File: armv5te/OP_AGET.S */
2066    /*
2067     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2068     *
2069     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2070     * instructions.  We use a pair of FETCH_Bs instead.
2071     *
2072     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2073     */
2074    /* op vAA, vBB, vCC */
2075    FETCH_B(r2, 1, 0)                   @ r2<- BB
2076    mov     r9, rINST, lsr #8           @ r9<- AA
2077    FETCH_B(r3, 1, 1)                   @ r3<- CC
2078    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2079    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2080    cmp     r0, #0                      @ null array object?
2081    beq     common_errNullObject        @ yes, bail
2082    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2083    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2084    cmp     r1, r3                      @ compare unsigned index, length
2085    bcs     common_errArrayIndex        @ index >= length, bail
2086    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2087    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2088    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2089    SET_VREG(r2, r9)                    @ vAA<- r2
2090    GOTO_OPCODE(ip)                     @ jump to next instruction
2091
2092
2093
2094/* ------------------------------ */
2095    .balign 64
2096.L_OP_AGET_BOOLEAN: /* 0x47 */
2097/* File: armv5te/OP_AGET_BOOLEAN.S */
2098/* File: armv5te/OP_AGET.S */
2099    /*
2100     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2101     *
2102     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2103     * instructions.  We use a pair of FETCH_Bs instead.
2104     *
2105     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2106     */
2107    /* op vAA, vBB, vCC */
2108    FETCH_B(r2, 1, 0)                   @ r2<- BB
2109    mov     r9, rINST, lsr #8           @ r9<- AA
2110    FETCH_B(r3, 1, 1)                   @ r3<- CC
2111    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2112    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2113    cmp     r0, #0                      @ null array object?
2114    beq     common_errNullObject        @ yes, bail
2115    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2116    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2117    cmp     r1, r3                      @ compare unsigned index, length
2118    bcs     common_errArrayIndex        @ index >= length, bail
2119    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2120    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2122    SET_VREG(r2, r9)                    @ vAA<- r2
2123    GOTO_OPCODE(ip)                     @ jump to next instruction
2124
2125
2126
2127/* ------------------------------ */
2128    .balign 64
2129.L_OP_AGET_BYTE: /* 0x48 */
2130/* File: armv5te/OP_AGET_BYTE.S */
2131/* File: armv5te/OP_AGET.S */
2132    /*
2133     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2134     *
2135     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2136     * instructions.  We use a pair of FETCH_Bs instead.
2137     *
2138     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2139     */
2140    /* op vAA, vBB, vCC */
2141    FETCH_B(r2, 1, 0)                   @ r2<- BB
2142    mov     r9, rINST, lsr #8           @ r9<- AA
2143    FETCH_B(r3, 1, 1)                   @ r3<- CC
2144    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2145    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2146    cmp     r0, #0                      @ null array object?
2147    beq     common_errNullObject        @ yes, bail
2148    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2149    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2150    cmp     r1, r3                      @ compare unsigned index, length
2151    bcs     common_errArrayIndex        @ index >= length, bail
2152    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2153    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2155    SET_VREG(r2, r9)                    @ vAA<- r2
2156    GOTO_OPCODE(ip)                     @ jump to next instruction
2157
2158
2159
2160/* ------------------------------ */
2161    .balign 64
2162.L_OP_AGET_CHAR: /* 0x49 */
2163/* File: armv5te/OP_AGET_CHAR.S */
2164/* File: armv5te/OP_AGET.S */
2165    /*
2166     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2167     *
2168     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2169     * instructions.  We use a pair of FETCH_Bs instead.
2170     *
2171     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2172     */
2173    /* op vAA, vBB, vCC */
2174    FETCH_B(r2, 1, 0)                   @ r2<- BB
2175    mov     r9, rINST, lsr #8           @ r9<- AA
2176    FETCH_B(r3, 1, 1)                   @ r3<- CC
2177    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2178    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2179    cmp     r0, #0                      @ null array object?
2180    beq     common_errNullObject        @ yes, bail
2181    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2182    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2183    cmp     r1, r3                      @ compare unsigned index, length
2184    bcs     common_errArrayIndex        @ index >= length, bail
2185    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2186    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2187    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2188    SET_VREG(r2, r9)                    @ vAA<- r2
2189    GOTO_OPCODE(ip)                     @ jump to next instruction
2190
2191
2192
2193/* ------------------------------ */
2194    .balign 64
2195.L_OP_AGET_SHORT: /* 0x4a */
2196/* File: armv5te/OP_AGET_SHORT.S */
2197/* File: armv5te/OP_AGET.S */
2198    /*
2199     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2200     *
2201     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2202     * instructions.  We use a pair of FETCH_Bs instead.
2203     *
2204     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2205     */
2206    /* op vAA, vBB, vCC */
2207    FETCH_B(r2, 1, 0)                   @ r2<- BB
2208    mov     r9, rINST, lsr #8           @ r9<- AA
2209    FETCH_B(r3, 1, 1)                   @ r3<- CC
2210    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2211    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2212    cmp     r0, #0                      @ null array object?
2213    beq     common_errNullObject        @ yes, bail
2214    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2215    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2216    cmp     r1, r3                      @ compare unsigned index, length
2217    bcs     common_errArrayIndex        @ index >= length, bail
2218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2219    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2221    SET_VREG(r2, r9)                    @ vAA<- r2
2222    GOTO_OPCODE(ip)                     @ jump to next instruction
2223
2224
2225
2226/* ------------------------------ */
2227    .balign 64
2228.L_OP_APUT: /* 0x4b */
2229/* File: armv5te/OP_APUT.S */
2230    /*
2231     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2232     *
2233     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2234     * instructions.  We use a pair of FETCH_Bs instead.
2235     *
2236     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2237     */
2238    /* op vAA, vBB, vCC */
2239    FETCH_B(r2, 1, 0)                   @ r2<- BB
2240    mov     r9, rINST, lsr #8           @ r9<- AA
2241    FETCH_B(r3, 1, 1)                   @ r3<- CC
2242    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2243    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2244    cmp     r0, #0                      @ null array object?
2245    beq     common_errNullObject        @ yes, bail
2246    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2247    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2248    cmp     r1, r3                      @ compare unsigned index, length
2249    bcs     common_errArrayIndex        @ index >= length, bail
2250    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2251    GET_VREG(r2, r9)                    @ r2<- vAA
2252    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2253    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2254    GOTO_OPCODE(ip)                     @ jump to next instruction
2255
2256
2257/* ------------------------------ */
2258    .balign 64
2259.L_OP_APUT_WIDE: /* 0x4c */
2260/* File: armv5te/OP_APUT_WIDE.S */
2261    /*
2262     * Array put, 64 bits.  vBB[vCC] <- vAA.
2263     *
2264     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2265     */
2266    /* aput-wide vAA, vBB, vCC */
2267    FETCH(r0, 1)                        @ r0<- CCBB
2268    mov     r9, rINST, lsr #8           @ r9<- AA
2269    and     r2, r0, #255                @ r2<- BB
2270    mov     r3, r0, lsr #8              @ r3<- CC
2271    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2272    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2273    cmp     r0, #0                      @ null array object?
2274    beq     common_errNullObject        @ yes, bail
2275    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2276    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2277    cmp     r1, r3                      @ compare unsigned index, length
2278    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2279    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2280    b       common_errArrayIndex        @ index >= length, bail
2281    @ May want to swap the order of these two branches depending on how the
2282    @ branch prediction (if any) handles conditional forward branches vs.
2283    @ unconditional forward branches.
2284
2285/* ------------------------------ */
2286    .balign 64
2287.L_OP_APUT_OBJECT: /* 0x4d */
2288/* File: armv5te/OP_APUT_OBJECT.S */
2289    /*
2290     * Store an object into an array.  vBB[vCC] <- vAA.
2291     *
2292     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2293     * instructions.  We use a pair of FETCH_Bs instead.
2294     */
2295    /* op vAA, vBB, vCC */
2296    FETCH(r0, 1)                        @ r0<- CCBB
2297    mov     r9, rINST, lsr #8           @ r9<- AA
2298    and     r2, r0, #255                @ r2<- BB
2299    mov     r3, r0, lsr #8              @ r3<- CC
2300    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2301    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2302    cmp     r1, #0                      @ null array object?
2303    GET_VREG(r9, r9)                    @ r9<- vAA
2304    beq     common_errNullObject        @ yes, bail
2305    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2306    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2307    cmp     r0, r3                      @ compare unsigned index, length
2308    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2309    b       common_errArrayIndex        @ index >= length, bail
2310
2311
2312/* ------------------------------ */
2313    .balign 64
2314.L_OP_APUT_BOOLEAN: /* 0x4e */
2315/* File: armv5te/OP_APUT_BOOLEAN.S */
2316/* File: armv5te/OP_APUT.S */
2317    /*
2318     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2319     *
2320     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2321     * instructions.  We use a pair of FETCH_Bs instead.
2322     *
2323     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2324     */
2325    /* op vAA, vBB, vCC */
2326    FETCH_B(r2, 1, 0)                   @ r2<- BB
2327    mov     r9, rINST, lsr #8           @ r9<- AA
2328    FETCH_B(r3, 1, 1)                   @ r3<- CC
2329    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2330    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2331    cmp     r0, #0                      @ null array object?
2332    beq     common_errNullObject        @ yes, bail
2333    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2334    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2335    cmp     r1, r3                      @ compare unsigned index, length
2336    bcs     common_errArrayIndex        @ index >= length, bail
2337    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2338    GET_VREG(r2, r9)                    @ r2<- vAA
2339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2340    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2341    GOTO_OPCODE(ip)                     @ jump to next instruction
2342
2343
2344
2345/* ------------------------------ */
2346    .balign 64
2347.L_OP_APUT_BYTE: /* 0x4f */
2348/* File: armv5te/OP_APUT_BYTE.S */
2349/* File: armv5te/OP_APUT.S */
2350    /*
2351     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2352     *
2353     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2354     * instructions.  We use a pair of FETCH_Bs instead.
2355     *
2356     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2357     */
2358    /* op vAA, vBB, vCC */
2359    FETCH_B(r2, 1, 0)                   @ r2<- BB
2360    mov     r9, rINST, lsr #8           @ r9<- AA
2361    FETCH_B(r3, 1, 1)                   @ r3<- CC
2362    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2363    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2364    cmp     r0, #0                      @ null array object?
2365    beq     common_errNullObject        @ yes, bail
2366    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2367    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2368    cmp     r1, r3                      @ compare unsigned index, length
2369    bcs     common_errArrayIndex        @ index >= length, bail
2370    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2371    GET_VREG(r2, r9)                    @ r2<- vAA
2372    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2373    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2374    GOTO_OPCODE(ip)                     @ jump to next instruction
2375
2376
2377
2378/* ------------------------------ */
2379    .balign 64
2380.L_OP_APUT_CHAR: /* 0x50 */
2381/* File: armv5te/OP_APUT_CHAR.S */
2382/* File: armv5te/OP_APUT.S */
2383    /*
2384     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2385     *
2386     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2387     * instructions.  We use a pair of FETCH_Bs instead.
2388     *
2389     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2390     */
2391    /* op vAA, vBB, vCC */
2392    FETCH_B(r2, 1, 0)                   @ r2<- BB
2393    mov     r9, rINST, lsr #8           @ r9<- AA
2394    FETCH_B(r3, 1, 1)                   @ r3<- CC
2395    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2396    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2397    cmp     r0, #0                      @ null array object?
2398    beq     common_errNullObject        @ yes, bail
2399    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2400    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2401    cmp     r1, r3                      @ compare unsigned index, length
2402    bcs     common_errArrayIndex        @ index >= length, bail
2403    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2404    GET_VREG(r2, r9)                    @ r2<- vAA
2405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2406    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2407    GOTO_OPCODE(ip)                     @ jump to next instruction
2408
2409
2410
2411/* ------------------------------ */
2412    .balign 64
2413.L_OP_APUT_SHORT: /* 0x51 */
2414/* File: armv5te/OP_APUT_SHORT.S */
2415/* File: armv5te/OP_APUT.S */
2416    /*
2417     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2418     *
2419     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2420     * instructions.  We use a pair of FETCH_Bs instead.
2421     *
2422     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2423     */
2424    /* op vAA, vBB, vCC */
2425    FETCH_B(r2, 1, 0)                   @ r2<- BB
2426    mov     r9, rINST, lsr #8           @ r9<- AA
2427    FETCH_B(r3, 1, 1)                   @ r3<- CC
2428    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2429    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2430    cmp     r0, #0                      @ null array object?
2431    beq     common_errNullObject        @ yes, bail
2432    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2433    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2434    cmp     r1, r3                      @ compare unsigned index, length
2435    bcs     common_errArrayIndex        @ index >= length, bail
2436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2437    GET_VREG(r2, r9)                    @ r2<- vAA
2438    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2439    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2440    GOTO_OPCODE(ip)                     @ jump to next instruction
2441
2442
2443
2444/* ------------------------------ */
2445    .balign 64
2446.L_OP_IGET: /* 0x52 */
2447/* File: armv5te/OP_IGET.S */
2448    /*
2449     * General 32-bit instance field get.
2450     *
2451     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2452     */
2453    /* op vA, vB, field@CCCC */
2454    mov     r0, rINST, lsr #12          @ r0<- B
2455    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2456    FETCH(r1, 1)                        @ r1<- field ref CCCC
2457    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2458    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2459    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2460    cmp     r0, #0                      @ is resolved entry null?
2461    bne     .LOP_IGET_finish          @ no, already resolved
24628:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2463    EXPORT_PC()                         @ resolve() could throw
2464    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2465    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2466    cmp     r0, #0
2467    bne     .LOP_IGET_finish
2468    b       common_exceptionThrown
2469
2470/* ------------------------------ */
2471    .balign 64
2472.L_OP_IGET_WIDE: /* 0x53 */
2473/* File: armv5te/OP_IGET_WIDE.S */
2474    /*
2475     * Wide 32-bit instance field get.
2476     */
2477    /* iget-wide vA, vB, field@CCCC */
2478    mov     r0, rINST, lsr #12          @ r0<- B
2479    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2480    FETCH(r1, 1)                        @ r1<- field ref CCCC
2481    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2482    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2483    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2484    cmp     r0, #0                      @ is resolved entry null?
2485    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24868:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2487    EXPORT_PC()                         @ resolve() could throw
2488    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2489    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2490    cmp     r0, #0
2491    bne     .LOP_IGET_WIDE_finish
2492    b       common_exceptionThrown
2493
2494/* ------------------------------ */
2495    .balign 64
2496.L_OP_IGET_OBJECT: /* 0x54 */
2497/* File: armv5te/OP_IGET_OBJECT.S */
2498/* File: armv5te/OP_IGET.S */
2499    /*
2500     * General 32-bit instance field get.
2501     *
2502     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2503     */
2504    /* op vA, vB, field@CCCC */
2505    mov     r0, rINST, lsr #12          @ r0<- B
2506    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2507    FETCH(r1, 1)                        @ r1<- field ref CCCC
2508    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2509    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2510    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2511    cmp     r0, #0                      @ is resolved entry null?
2512    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2514    EXPORT_PC()                         @ resolve() could throw
2515    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2516    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2517    cmp     r0, #0
2518    bne     .LOP_IGET_OBJECT_finish
2519    b       common_exceptionThrown
2520
2521
2522/* ------------------------------ */
2523    .balign 64
2524.L_OP_IGET_BOOLEAN: /* 0x55 */
2525/* File: armv5te/OP_IGET_BOOLEAN.S */
2526@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2527/* File: armv5te/OP_IGET.S */
2528    /*
2529     * General 32-bit instance field get.
2530     *
2531     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2532     */
2533    /* op vA, vB, field@CCCC */
2534    mov     r0, rINST, lsr #12          @ r0<- B
2535    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2536    FETCH(r1, 1)                        @ r1<- field ref CCCC
2537    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2538    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2539    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2540    cmp     r0, #0                      @ is resolved entry null?
2541    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25428:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2543    EXPORT_PC()                         @ resolve() could throw
2544    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2545    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2546    cmp     r0, #0
2547    bne     .LOP_IGET_BOOLEAN_finish
2548    b       common_exceptionThrown
2549
2550
2551/* ------------------------------ */
2552    .balign 64
2553.L_OP_IGET_BYTE: /* 0x56 */
2554/* File: armv5te/OP_IGET_BYTE.S */
2555@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2556/* File: armv5te/OP_IGET.S */
2557    /*
2558     * General 32-bit instance field get.
2559     *
2560     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2561     */
2562    /* op vA, vB, field@CCCC */
2563    mov     r0, rINST, lsr #12          @ r0<- B
2564    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2565    FETCH(r1, 1)                        @ r1<- field ref CCCC
2566    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2567    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2568    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2569    cmp     r0, #0                      @ is resolved entry null?
2570    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2572    EXPORT_PC()                         @ resolve() could throw
2573    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2574    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2575    cmp     r0, #0
2576    bne     .LOP_IGET_BYTE_finish
2577    b       common_exceptionThrown
2578
2579
2580/* ------------------------------ */
2581    .balign 64
2582.L_OP_IGET_CHAR: /* 0x57 */
2583/* File: armv5te/OP_IGET_CHAR.S */
2584@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2585/* File: armv5te/OP_IGET.S */
2586    /*
2587     * General 32-bit instance field get.
2588     *
2589     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2590     */
2591    /* op vA, vB, field@CCCC */
2592    mov     r0, rINST, lsr #12          @ r0<- B
2593    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2594    FETCH(r1, 1)                        @ r1<- field ref CCCC
2595    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2596    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2597    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2598    cmp     r0, #0                      @ is resolved entry null?
2599    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
26008:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2601    EXPORT_PC()                         @ resolve() could throw
2602    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2603    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2604    cmp     r0, #0
2605    bne     .LOP_IGET_CHAR_finish
2606    b       common_exceptionThrown
2607
2608
2609/* ------------------------------ */
2610    .balign 64
2611.L_OP_IGET_SHORT: /* 0x58 */
2612/* File: armv5te/OP_IGET_SHORT.S */
2613@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2614/* File: armv5te/OP_IGET.S */
2615    /*
2616     * General 32-bit instance field get.
2617     *
2618     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2619     */
2620    /* op vA, vB, field@CCCC */
2621    mov     r0, rINST, lsr #12          @ r0<- B
2622    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2623    FETCH(r1, 1)                        @ r1<- field ref CCCC
2624    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2625    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2626    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2627    cmp     r0, #0                      @ is resolved entry null?
2628    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2630    EXPORT_PC()                         @ resolve() could throw
2631    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2632    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2633    cmp     r0, #0
2634    bne     .LOP_IGET_SHORT_finish
2635    b       common_exceptionThrown
2636
2637
2638/* ------------------------------ */
2639    .balign 64
2640.L_OP_IPUT: /* 0x59 */
2641/* File: armv5te/OP_IPUT.S */
2642    /*
2643     * General 32-bit instance field put.
2644     *
2645     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2646     */
2647    /* op vA, vB, field@CCCC */
2648    mov     r0, rINST, lsr #12          @ r0<- B
2649    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2650    FETCH(r1, 1)                        @ r1<- field ref CCCC
2651    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2652    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2653    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2654    cmp     r0, #0                      @ is resolved entry null?
2655    bne     .LOP_IPUT_finish          @ no, already resolved
26568:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2657    EXPORT_PC()                         @ resolve() could throw
2658    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2659    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2660    cmp     r0, #0                      @ success?
2661    bne     .LOP_IPUT_finish          @ yes, finish up
2662    b       common_exceptionThrown
2663
2664/* ------------------------------ */
2665    .balign 64
2666.L_OP_IPUT_WIDE: /* 0x5a */
2667/* File: armv5te/OP_IPUT_WIDE.S */
2668    /* iput-wide vA, vB, field@CCCC */
2669    mov     r0, rINST, lsr #12          @ r0<- B
2670    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2671    FETCH(r1, 1)                        @ r1<- field ref CCCC
2672    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2673    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2674    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2675    cmp     r0, #0                      @ is resolved entry null?
2676    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26778:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2678    EXPORT_PC()                         @ resolve() could throw
2679    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2680    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2681    cmp     r0, #0                      @ success?
2682    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2683    b       common_exceptionThrown
2684
2685/* ------------------------------ */
2686    .balign 64
2687.L_OP_IPUT_OBJECT: /* 0x5b */
2688/* File: armv5te/OP_IPUT_OBJECT.S */
2689/* File: armv5te/OP_IPUT.S */
2690    /*
2691     * General 32-bit instance field put.
2692     *
2693     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2694     */
2695    /* op vA, vB, field@CCCC */
2696    mov     r0, rINST, lsr #12          @ r0<- B
2697    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2698    FETCH(r1, 1)                        @ r1<- field ref CCCC
2699    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2700    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2701    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2702    cmp     r0, #0                      @ is resolved entry null?
2703    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
27048:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2705    EXPORT_PC()                         @ resolve() could throw
2706    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2707    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2708    cmp     r0, #0                      @ success?
2709    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2710    b       common_exceptionThrown
2711
2712
2713/* ------------------------------ */
2714    .balign 64
2715.L_OP_IPUT_BOOLEAN: /* 0x5c */
2716/* File: armv5te/OP_IPUT_BOOLEAN.S */
2717@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2718/* File: armv5te/OP_IPUT.S */
2719    /*
2720     * General 32-bit instance field put.
2721     *
2722     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2723     */
2724    /* op vA, vB, field@CCCC */
2725    mov     r0, rINST, lsr #12          @ r0<- B
2726    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2727    FETCH(r1, 1)                        @ r1<- field ref CCCC
2728    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2729    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2730    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2731    cmp     r0, #0                      @ is resolved entry null?
2732    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27338:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2734    EXPORT_PC()                         @ resolve() could throw
2735    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2736    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2737    cmp     r0, #0                      @ success?
2738    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2739    b       common_exceptionThrown
2740
2741
2742/* ------------------------------ */
2743    .balign 64
2744.L_OP_IPUT_BYTE: /* 0x5d */
2745/* File: armv5te/OP_IPUT_BYTE.S */
2746@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2747/* File: armv5te/OP_IPUT.S */
2748    /*
2749     * General 32-bit instance field put.
2750     *
2751     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2752     */
2753    /* op vA, vB, field@CCCC */
2754    mov     r0, rINST, lsr #12          @ r0<- B
2755    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2756    FETCH(r1, 1)                        @ r1<- field ref CCCC
2757    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2758    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2759    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2760    cmp     r0, #0                      @ is resolved entry null?
2761    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27628:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2763    EXPORT_PC()                         @ resolve() could throw
2764    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2765    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2766    cmp     r0, #0                      @ success?
2767    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2768    b       common_exceptionThrown
2769
2770
2771/* ------------------------------ */
2772    .balign 64
2773.L_OP_IPUT_CHAR: /* 0x5e */
2774/* File: armv5te/OP_IPUT_CHAR.S */
2775@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2776/* File: armv5te/OP_IPUT.S */
2777    /*
2778     * General 32-bit instance field put.
2779     *
2780     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2781     */
2782    /* op vA, vB, field@CCCC */
2783    mov     r0, rINST, lsr #12          @ r0<- B
2784    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2785    FETCH(r1, 1)                        @ r1<- field ref CCCC
2786    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2787    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2788    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2789    cmp     r0, #0                      @ is resolved entry null?
2790    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27918:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2792    EXPORT_PC()                         @ resolve() could throw
2793    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2794    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2795    cmp     r0, #0                      @ success?
2796    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2797    b       common_exceptionThrown
2798
2799
2800/* ------------------------------ */
2801    .balign 64
2802.L_OP_IPUT_SHORT: /* 0x5f */
2803/* File: armv5te/OP_IPUT_SHORT.S */
2804@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2805/* File: armv5te/OP_IPUT.S */
2806    /*
2807     * General 32-bit instance field put.
2808     *
2809     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2810     */
2811    /* op vA, vB, field@CCCC */
2812    mov     r0, rINST, lsr #12          @ r0<- B
2813    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2814    FETCH(r1, 1)                        @ r1<- field ref CCCC
2815    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2816    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2817    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2818    cmp     r0, #0                      @ is resolved entry null?
2819    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28208:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2821    EXPORT_PC()                         @ resolve() could throw
2822    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2823    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2824    cmp     r0, #0                      @ success?
2825    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2826    b       common_exceptionThrown
2827
2828
2829/* ------------------------------ */
2830    .balign 64
2831.L_OP_SGET: /* 0x60 */
2832/* File: armv5te/OP_SGET.S */
2833    /*
2834     * General 32-bit SGET handler.
2835     *
2836     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2837     */
2838    /* op vAA, field@BBBB */
2839    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2840    FETCH(r1, 1)                        @ r1<- field ref BBBB
2841    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2842    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2843    cmp     r0, #0                      @ is resolved entry null?
2844    beq     .LOP_SGET_resolve         @ yes, do resolve
2845.LOP_SGET_finish: @ field ptr in r0
2846    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2847    mov     r2, rINST, lsr #8           @ r2<- AA
2848    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2849    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2851    GOTO_OPCODE(ip)                     @ jump to next instruction
2852
2853/* ------------------------------ */
2854    .balign 64
2855.L_OP_SGET_WIDE: /* 0x61 */
2856/* File: armv5te/OP_SGET_WIDE.S */
2857    /*
2858     * 64-bit SGET handler.
2859     */
2860    /* sget-wide vAA, field@BBBB */
2861    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2862    FETCH(r1, 1)                        @ r1<- field ref BBBB
2863    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2864    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2865    cmp     r0, #0                      @ is resolved entry null?
2866    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2867.LOP_SGET_WIDE_finish:
2868    mov     r1, rINST, lsr #8           @ r1<- AA
2869    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2870    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2871    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2872    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2874    GOTO_OPCODE(ip)                     @ jump to next instruction
2875
2876/* ------------------------------ */
2877    .balign 64
2878.L_OP_SGET_OBJECT: /* 0x62 */
2879/* File: armv5te/OP_SGET_OBJECT.S */
2880/* File: armv5te/OP_SGET.S */
2881    /*
2882     * General 32-bit SGET handler.
2883     *
2884     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2885     */
2886    /* op vAA, field@BBBB */
2887    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2888    FETCH(r1, 1)                        @ r1<- field ref BBBB
2889    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2890    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2891    cmp     r0, #0                      @ is resolved entry null?
2892    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2893.LOP_SGET_OBJECT_finish: @ field ptr in r0
2894    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2895    mov     r2, rINST, lsr #8           @ r2<- AA
2896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2897    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2899    GOTO_OPCODE(ip)                     @ jump to next instruction
2900
2901
2902/* ------------------------------ */
2903    .balign 64
2904.L_OP_SGET_BOOLEAN: /* 0x63 */
2905/* File: armv5te/OP_SGET_BOOLEAN.S */
2906/* File: armv5te/OP_SGET.S */
2907    /*
2908     * General 32-bit SGET handler.
2909     *
2910     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2911     */
2912    /* op vAA, field@BBBB */
2913    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2914    FETCH(r1, 1)                        @ r1<- field ref BBBB
2915    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2916    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2917    cmp     r0, #0                      @ is resolved entry null?
2918    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2919.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2920    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2921    mov     r2, rINST, lsr #8           @ r2<- AA
2922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2923    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2925    GOTO_OPCODE(ip)                     @ jump to next instruction
2926
2927
2928/* ------------------------------ */
2929    .balign 64
2930.L_OP_SGET_BYTE: /* 0x64 */
2931/* File: armv5te/OP_SGET_BYTE.S */
2932/* File: armv5te/OP_SGET.S */
2933    /*
2934     * General 32-bit SGET handler.
2935     *
2936     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2937     */
2938    /* op vAA, field@BBBB */
2939    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2940    FETCH(r1, 1)                        @ r1<- field ref BBBB
2941    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2942    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2943    cmp     r0, #0                      @ is resolved entry null?
2944    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2945.LOP_SGET_BYTE_finish: @ field ptr in r0
2946    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2947    mov     r2, rINST, lsr #8           @ r2<- AA
2948    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2949    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2951    GOTO_OPCODE(ip)                     @ jump to next instruction
2952
2953
2954/* ------------------------------ */
2955    .balign 64
2956.L_OP_SGET_CHAR: /* 0x65 */
2957/* File: armv5te/OP_SGET_CHAR.S */
2958/* File: armv5te/OP_SGET.S */
2959    /*
2960     * General 32-bit SGET handler.
2961     *
2962     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2963     */
2964    /* op vAA, field@BBBB */
2965    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2966    FETCH(r1, 1)                        @ r1<- field ref BBBB
2967    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2968    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2969    cmp     r0, #0                      @ is resolved entry null?
2970    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2971.LOP_SGET_CHAR_finish: @ field ptr in r0
2972    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2973    mov     r2, rINST, lsr #8           @ r2<- AA
2974    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2975    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2977    GOTO_OPCODE(ip)                     @ jump to next instruction
2978
2979
2980/* ------------------------------ */
2981    .balign 64
2982.L_OP_SGET_SHORT: /* 0x66 */
2983/* File: armv5te/OP_SGET_SHORT.S */
2984/* File: armv5te/OP_SGET.S */
2985    /*
2986     * General 32-bit SGET handler.
2987     *
2988     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2989     */
2990    /* op vAA, field@BBBB */
2991    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2992    FETCH(r1, 1)                        @ r1<- field ref BBBB
2993    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2994    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2995    cmp     r0, #0                      @ is resolved entry null?
2996    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2997.LOP_SGET_SHORT_finish: @ field ptr in r0
2998    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2999    mov     r2, rINST, lsr #8           @ r2<- AA
3000    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3001    SET_VREG(r1, r2)                    @ fp[AA]<- r1
3002    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3003    GOTO_OPCODE(ip)                     @ jump to next instruction
3004
3005
3006/* ------------------------------ */
3007    .balign 64
3008.L_OP_SPUT: /* 0x67 */
3009/* File: armv5te/OP_SPUT.S */
3010    /*
3011     * General 32-bit SPUT handler.
3012     *
3013     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3014     */
3015    /* op vAA, field@BBBB */
3016    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3017    FETCH(r1, 1)                        @ r1<- field ref BBBB
3018    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3019    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3020    cmp     r0, #0                      @ is resolved entry null?
3021    beq     .LOP_SPUT_resolve         @ yes, do resolve
3022.LOP_SPUT_finish:   @ field ptr in r0
3023    mov     r2, rINST, lsr #8           @ r2<- AA
3024    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3025    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3026    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3027    str     r1, [r0, #offStaticField_value] @ field<- vAA
3028    GOTO_OPCODE(ip)                     @ jump to next instruction
3029
3030/* ------------------------------ */
3031    .balign 64
3032.L_OP_SPUT_WIDE: /* 0x68 */
3033/* File: armv5te/OP_SPUT_WIDE.S */
3034    /*
3035     * 64-bit SPUT handler.
3036     */
3037    /* sput-wide vAA, field@BBBB */
3038    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3039    FETCH(r1, 1)                        @ r1<- field ref BBBB
3040    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3041    mov     r9, rINST, lsr #8           @ r9<- AA
3042    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3043    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3044    cmp     r0, #0                      @ is resolved entry null?
3045    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3046.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3047    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3048    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3049    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3050    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3051    GOTO_OPCODE(ip)                     @ jump to next instruction
3052
3053/* ------------------------------ */
3054    .balign 64
3055.L_OP_SPUT_OBJECT: /* 0x69 */
3056/* File: armv5te/OP_SPUT_OBJECT.S */
3057/* File: armv5te/OP_SPUT.S */
3058    /*
3059     * General 32-bit SPUT handler.
3060     *
3061     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3062     */
3063    /* op vAA, field@BBBB */
3064    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3065    FETCH(r1, 1)                        @ r1<- field ref BBBB
3066    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3067    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3068    cmp     r0, #0                      @ is resolved entry null?
3069    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3070.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3071    mov     r2, rINST, lsr #8           @ r2<- AA
3072    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3073    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3074    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3075    str     r1, [r0, #offStaticField_value] @ field<- vAA
3076    GOTO_OPCODE(ip)                     @ jump to next instruction
3077
3078
3079/* ------------------------------ */
3080    .balign 64
3081.L_OP_SPUT_BOOLEAN: /* 0x6a */
3082/* File: armv5te/OP_SPUT_BOOLEAN.S */
3083/* File: armv5te/OP_SPUT.S */
3084    /*
3085     * General 32-bit SPUT handler.
3086     *
3087     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3088     */
3089    /* op vAA, field@BBBB */
3090    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3091    FETCH(r1, 1)                        @ r1<- field ref BBBB
3092    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3093    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3094    cmp     r0, #0                      @ is resolved entry null?
3095    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3096.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3097    mov     r2, rINST, lsr #8           @ r2<- AA
3098    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3099    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3100    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3101    str     r1, [r0, #offStaticField_value] @ field<- vAA
3102    GOTO_OPCODE(ip)                     @ jump to next instruction
3103
3104
3105/* ------------------------------ */
3106    .balign 64
3107.L_OP_SPUT_BYTE: /* 0x6b */
3108/* File: armv5te/OP_SPUT_BYTE.S */
3109/* File: armv5te/OP_SPUT.S */
3110    /*
3111     * General 32-bit SPUT handler.
3112     *
3113     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3114     */
3115    /* op vAA, field@BBBB */
3116    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3117    FETCH(r1, 1)                        @ r1<- field ref BBBB
3118    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3119    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3120    cmp     r0, #0                      @ is resolved entry null?
3121    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3122.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3123    mov     r2, rINST, lsr #8           @ r2<- AA
3124    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3125    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3126    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3127    str     r1, [r0, #offStaticField_value] @ field<- vAA
3128    GOTO_OPCODE(ip)                     @ jump to next instruction
3129
3130
3131/* ------------------------------ */
3132    .balign 64
3133.L_OP_SPUT_CHAR: /* 0x6c */
3134/* File: armv5te/OP_SPUT_CHAR.S */
3135/* File: armv5te/OP_SPUT.S */
3136    /*
3137     * General 32-bit SPUT handler.
3138     *
3139     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3140     */
3141    /* op vAA, field@BBBB */
3142    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3143    FETCH(r1, 1)                        @ r1<- field ref BBBB
3144    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3145    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3146    cmp     r0, #0                      @ is resolved entry null?
3147    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3148.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3149    mov     r2, rINST, lsr #8           @ r2<- AA
3150    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3151    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3153    str     r1, [r0, #offStaticField_value] @ field<- vAA
3154    GOTO_OPCODE(ip)                     @ jump to next instruction
3155
3156
3157/* ------------------------------ */
3158    .balign 64
3159.L_OP_SPUT_SHORT: /* 0x6d */
3160/* File: armv5te/OP_SPUT_SHORT.S */
3161/* File: armv5te/OP_SPUT.S */
3162    /*
3163     * General 32-bit SPUT handler.
3164     *
3165     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3166     */
3167    /* op vAA, field@BBBB */
3168    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3169    FETCH(r1, 1)                        @ r1<- field ref BBBB
3170    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3171    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3172    cmp     r0, #0                      @ is resolved entry null?
3173    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3174.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3175    mov     r2, rINST, lsr #8           @ r2<- AA
3176    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3177    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3179    str     r1, [r0, #offStaticField_value] @ field<- vAA
3180    GOTO_OPCODE(ip)                     @ jump to next instruction
3181
3182
3183/* ------------------------------ */
3184    .balign 64
3185.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3186/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3187    /*
3188     * Handle a virtual method call.
3189     *
3190     * for: invoke-virtual, invoke-virtual/range
3191     */
3192    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3193    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3194    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3195    FETCH(r1, 1)                        @ r1<- BBBB
3196    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3197    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3198    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3199    .if     (!0)
3200    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3201    .endif
3202    cmp     r0, #0                      @ already resolved?
3203    EXPORT_PC()                         @ must export for invoke
3204    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3205    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3206    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3207    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3208    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3209    cmp     r0, #0                      @ got null?
3210    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3211    b       common_exceptionThrown      @ yes, handle exception
3212
3213/* ------------------------------ */
3214    .balign 64
3215.L_OP_INVOKE_SUPER: /* 0x6f */
3216/* File: armv5te/OP_INVOKE_SUPER.S */
3217    /*
3218     * Handle a "super" method call.
3219     *
3220     * for: invoke-super, invoke-super/range
3221     */
3222    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3223    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3224    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3225    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3226    .if     (!0)
3227    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3228    .endif
3229    FETCH(r1, 1)                        @ r1<- BBBB
3230    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3231    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3232    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3233    cmp     r2, #0                      @ null "this"?
3234    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3235    beq     common_errNullObject        @ null "this", throw exception
3236    cmp     r0, #0                      @ already resolved?
3237    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3238    EXPORT_PC()                         @ must export for invoke
3239    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3240    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3241
3242/* ------------------------------ */
3243    .balign 64
3244.L_OP_INVOKE_DIRECT: /* 0x70 */
3245/* File: armv5te/OP_INVOKE_DIRECT.S */
3246    /*
3247     * Handle a direct method call.
3248     *
3249     * (We could defer the "is 'this' pointer null" test to the common
3250     * method invocation code, and use a flag to indicate that static
3251     * calls don't count.  If we do this as part of copying the arguments
3252     * out we could avoiding loading the first arg twice.)
3253     *
3254     * for: invoke-direct, invoke-direct/range
3255     */
3256    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3257    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3258    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3259    FETCH(r1, 1)                        @ r1<- BBBB
3260    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3261    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3262    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3263    .if     (!0)
3264    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3265    .endif
3266    cmp     r0, #0                      @ already resolved?
3267    EXPORT_PC()                         @ must export for invoke
3268    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3269    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3270.LOP_INVOKE_DIRECT_finish:
3271    cmp     r2, #0                      @ null "this" ref?
3272    bne     common_invokeMethodNoRange   @ no, continue on
3273    b       common_errNullObject        @ yes, throw exception
3274
3275/* ------------------------------ */
3276    .balign 64
3277.L_OP_INVOKE_STATIC: /* 0x71 */
3278/* File: armv5te/OP_INVOKE_STATIC.S */
3279    /*
3280     * Handle a static method call.
3281     *
3282     * for: invoke-static, invoke-static/range
3283     */
3284    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3285    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3286    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3287    FETCH(r1, 1)                        @ r1<- BBBB
3288    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3289    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3290    cmp     r0, #0                      @ already resolved?
3291    EXPORT_PC()                         @ must export for invoke
3292    bne     common_invokeMethodNoRange @ yes, continue on
32930:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3294    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3295    mov     r2, #METHOD_STATIC          @ resolver method type
3296    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3297    cmp     r0, #0                      @ got null?
3298    bne     common_invokeMethodNoRange @ no, continue
3299    b       common_exceptionThrown      @ yes, handle exception
3300
3301
3302/* ------------------------------ */
3303    .balign 64
3304.L_OP_INVOKE_INTERFACE: /* 0x72 */
3305/* File: armv5te/OP_INVOKE_INTERFACE.S */
3306    /*
3307     * Handle an interface method call.
3308     *
3309     * for: invoke-interface, invoke-interface/range
3310     */
3311    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3312    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3313    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3314    FETCH(r1, 1)                        @ r1<- BBBB
3315    .if     (!0)
3316    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3317    .endif
3318    EXPORT_PC()                         @ must export for invoke
3319    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3320    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3321    cmp     r0, #0                      @ null obj?
3322    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3323    beq     common_errNullObject        @ yes, fail
3324    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3325    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3326    cmp     r0, #0                      @ failed?
3327    beq     common_exceptionThrown      @ yes, handle exception
3328    b       common_invokeMethodNoRange @ jump to common handler
3329
3330
3331/* ------------------------------ */
3332    .balign 64
3333.L_OP_UNUSED_73: /* 0x73 */
3334/* File: armv5te/OP_UNUSED_73.S */
3335/* File: armv5te/unused.S */
3336    bl      common_abort
3337
3338
3339
3340/* ------------------------------ */
3341    .balign 64
3342.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3343/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3344/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3345    /*
3346     * Handle a virtual method call.
3347     *
3348     * for: invoke-virtual, invoke-virtual/range
3349     */
3350    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3351    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3352    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3353    FETCH(r1, 1)                        @ r1<- BBBB
3354    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3355    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3356    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3357    .if     (!1)
3358    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3359    .endif
3360    cmp     r0, #0                      @ already resolved?
3361    EXPORT_PC()                         @ must export for invoke
3362    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3363    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3364    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3365    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3366    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3367    cmp     r0, #0                      @ got null?
3368    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3369    b       common_exceptionThrown      @ yes, handle exception
3370
3371
3372/* ------------------------------ */
3373    .balign 64
3374.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3375/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3376/* File: armv5te/OP_INVOKE_SUPER.S */
3377    /*
3378     * Handle a "super" method call.
3379     *
3380     * for: invoke-super, invoke-super/range
3381     */
3382    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3383    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3384    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3385    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3386    .if     (!1)
3387    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3388    .endif
3389    FETCH(r1, 1)                        @ r1<- BBBB
3390    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3391    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3392    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3393    cmp     r2, #0                      @ null "this"?
3394    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3395    beq     common_errNullObject        @ null "this", throw exception
3396    cmp     r0, #0                      @ already resolved?
3397    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3398    EXPORT_PC()                         @ must export for invoke
3399    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3400    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3401
3402
3403/* ------------------------------ */
3404    .balign 64
3405.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3406/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3407/* File: armv5te/OP_INVOKE_DIRECT.S */
3408    /*
3409     * Handle a direct method call.
3410     *
3411     * (We could defer the "is 'this' pointer null" test to the common
3412     * method invocation code, and use a flag to indicate that static
3413     * calls don't count.  If we do this as part of copying the arguments
3414     * out we could avoiding loading the first arg twice.)
3415     *
3416     * for: invoke-direct, invoke-direct/range
3417     */
3418    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3419    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3420    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3421    FETCH(r1, 1)                        @ r1<- BBBB
3422    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3423    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3424    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3425    .if     (!1)
3426    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3427    .endif
3428    cmp     r0, #0                      @ already resolved?
3429    EXPORT_PC()                         @ must export for invoke
3430    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3431    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3432.LOP_INVOKE_DIRECT_RANGE_finish:
3433    cmp     r2, #0                      @ null "this" ref?
3434    bne     common_invokeMethodRange   @ no, continue on
3435    b       common_errNullObject        @ yes, throw exception
3436
3437
3438/* ------------------------------ */
3439    .balign 64
3440.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3441/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3442/* File: armv5te/OP_INVOKE_STATIC.S */
3443    /*
3444     * Handle a static method call.
3445     *
3446     * for: invoke-static, invoke-static/range
3447     */
3448    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3449    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3450    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3451    FETCH(r1, 1)                        @ r1<- BBBB
3452    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3453    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3454    cmp     r0, #0                      @ already resolved?
3455    EXPORT_PC()                         @ must export for invoke
3456    bne     common_invokeMethodRange @ yes, continue on
34570:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3458    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3459    mov     r2, #METHOD_STATIC          @ resolver method type
3460    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3461    cmp     r0, #0                      @ got null?
3462    bne     common_invokeMethodRange @ no, continue
3463    b       common_exceptionThrown      @ yes, handle exception
3464
3465
3466
3467/* ------------------------------ */
3468    .balign 64
3469.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3470/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3471/* File: armv5te/OP_INVOKE_INTERFACE.S */
3472    /*
3473     * Handle an interface method call.
3474     *
3475     * for: invoke-interface, invoke-interface/range
3476     */
3477    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3478    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3479    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3480    FETCH(r1, 1)                        @ r1<- BBBB
3481    .if     (!1)
3482    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3483    .endif
3484    EXPORT_PC()                         @ must export for invoke
3485    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3486    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3487    cmp     r0, #0                      @ null obj?
3488    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3489    beq     common_errNullObject        @ yes, fail
3490    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3491    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3492    cmp     r0, #0                      @ failed?
3493    beq     common_exceptionThrown      @ yes, handle exception
3494    b       common_invokeMethodRange @ jump to common handler
3495
3496
3497
3498/* ------------------------------ */
3499    .balign 64
3500.L_OP_UNUSED_79: /* 0x79 */
3501/* File: armv5te/OP_UNUSED_79.S */
3502/* File: armv5te/unused.S */
3503    bl      common_abort
3504
3505
3506
3507/* ------------------------------ */
3508    .balign 64
3509.L_OP_UNUSED_7A: /* 0x7a */
3510/* File: armv5te/OP_UNUSED_7A.S */
3511/* File: armv5te/unused.S */
3512    bl      common_abort
3513
3514
3515
3516/* ------------------------------ */
3517    .balign 64
3518.L_OP_NEG_INT: /* 0x7b */
3519/* File: armv5te/OP_NEG_INT.S */
3520/* File: armv5te/unop.S */
3521    /*
3522     * Generic 32-bit unary operation.  Provide an "instr" line that
3523     * specifies an instruction that performs "result = op r0".
3524     * This could be an ARM instruction or a function call.
3525     *
3526     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3527     *      int-to-byte, int-to-char, int-to-short
3528     */
3529    /* unop vA, vB */
3530    mov     r3, rINST, lsr #12          @ r3<- B
3531    mov     r9, rINST, lsr #8           @ r9<- A+
3532    GET_VREG(r0, r3)                    @ r0<- vB
3533    and     r9, r9, #15
3534                               @ optional op; may set condition codes
3535    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3536    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3538    SET_VREG(r0, r9)                    @ vAA<- r0
3539    GOTO_OPCODE(ip)                     @ jump to next instruction
3540    /* 9-10 instructions */
3541
3542
3543/* ------------------------------ */
3544    .balign 64
3545.L_OP_NOT_INT: /* 0x7c */
3546/* File: armv5te/OP_NOT_INT.S */
3547/* File: armv5te/unop.S */
3548    /*
3549     * Generic 32-bit unary operation.  Provide an "instr" line that
3550     * specifies an instruction that performs "result = op r0".
3551     * This could be an ARM instruction or a function call.
3552     *
3553     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3554     *      int-to-byte, int-to-char, int-to-short
3555     */
3556    /* unop vA, vB */
3557    mov     r3, rINST, lsr #12          @ r3<- B
3558    mov     r9, rINST, lsr #8           @ r9<- A+
3559    GET_VREG(r0, r3)                    @ r0<- vB
3560    and     r9, r9, #15
3561                               @ optional op; may set condition codes
3562    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3563    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3565    SET_VREG(r0, r9)                    @ vAA<- r0
3566    GOTO_OPCODE(ip)                     @ jump to next instruction
3567    /* 9-10 instructions */
3568
3569
3570/* ------------------------------ */
3571    .balign 64
3572.L_OP_NEG_LONG: /* 0x7d */
3573/* File: armv5te/OP_NEG_LONG.S */
3574/* File: armv5te/unopWide.S */
3575    /*
3576     * Generic 64-bit unary operation.  Provide an "instr" line that
3577     * specifies an instruction that performs "result = op r0/r1".
3578     * This could be an ARM instruction or a function call.
3579     *
3580     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3581     */
3582    /* unop vA, vB */
3583    mov     r9, rINST, lsr #8           @ r9<- A+
3584    mov     r3, rINST, lsr #12          @ r3<- B
3585    and     r9, r9, #15
3586    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3587    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3588    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3589    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3590    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3591    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3592    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3593    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3594    GOTO_OPCODE(ip)                     @ jump to next instruction
3595    /* 12-13 instructions */
3596
3597
3598
3599/* ------------------------------ */
3600    .balign 64
3601.L_OP_NOT_LONG: /* 0x7e */
3602/* File: armv5te/OP_NOT_LONG.S */
3603/* File: armv5te/unopWide.S */
3604    /*
3605     * Generic 64-bit unary operation.  Provide an "instr" line that
3606     * specifies an instruction that performs "result = op r0/r1".
3607     * This could be an ARM instruction or a function call.
3608     *
3609     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3610     */
3611    /* unop vA, vB */
3612    mov     r9, rINST, lsr #8           @ r9<- A+
3613    mov     r3, rINST, lsr #12          @ r3<- B
3614    and     r9, r9, #15
3615    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3616    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3617    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3618    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3619    mvn     r0, r0                           @ optional op; may set condition codes
3620    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3621    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3622    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3623    GOTO_OPCODE(ip)                     @ jump to next instruction
3624    /* 12-13 instructions */
3625
3626
3627
3628/* ------------------------------ */
3629    .balign 64
3630.L_OP_NEG_FLOAT: /* 0x7f */
3631/* File: armv5te/OP_NEG_FLOAT.S */
3632/* File: armv5te/unop.S */
3633    /*
3634     * Generic 32-bit unary operation.  Provide an "instr" line that
3635     * specifies an instruction that performs "result = op r0".
3636     * This could be an ARM instruction or a function call.
3637     *
3638     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3639     *      int-to-byte, int-to-char, int-to-short
3640     */
3641    /* unop vA, vB */
3642    mov     r3, rINST, lsr #12          @ r3<- B
3643    mov     r9, rINST, lsr #8           @ r9<- A+
3644    GET_VREG(r0, r3)                    @ r0<- vB
3645    and     r9, r9, #15
3646                               @ optional op; may set condition codes
3647    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3648    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3650    SET_VREG(r0, r9)                    @ vAA<- r0
3651    GOTO_OPCODE(ip)                     @ jump to next instruction
3652    /* 9-10 instructions */
3653
3654
3655/* ------------------------------ */
3656    .balign 64
3657.L_OP_NEG_DOUBLE: /* 0x80 */
3658/* File: armv5te/OP_NEG_DOUBLE.S */
3659/* File: armv5te/unopWide.S */
3660    /*
3661     * Generic 64-bit unary operation.  Provide an "instr" line that
3662     * specifies an instruction that performs "result = op r0/r1".
3663     * This could be an ARM instruction or a function call.
3664     *
3665     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3666     */
3667    /* unop vA, vB */
3668    mov     r9, rINST, lsr #8           @ r9<- A+
3669    mov     r3, rINST, lsr #12          @ r3<- B
3670    and     r9, r9, #15
3671    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3672    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3673    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3674    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3675                               @ optional op; may set condition codes
3676    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3677    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3678    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3679    GOTO_OPCODE(ip)                     @ jump to next instruction
3680    /* 12-13 instructions */
3681
3682
3683
3684/* ------------------------------ */
3685    .balign 64
3686.L_OP_INT_TO_LONG: /* 0x81 */
3687/* File: armv5te/OP_INT_TO_LONG.S */
3688/* File: armv5te/unopWider.S */
3689    /*
3690     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3691     * that specifies an instruction that performs "result = op r0", where
3692     * "result" is a 64-bit quantity in r0/r1.
3693     *
3694     * For: int-to-long, int-to-double, float-to-long, float-to-double
3695     */
3696    /* unop vA, vB */
3697    mov     r9, rINST, lsr #8           @ r9<- A+
3698    mov     r3, rINST, lsr #12          @ r3<- B
3699    and     r9, r9, #15
3700    GET_VREG(r0, r3)                    @ r0<- vB
3701    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3702                               @ optional op; may set condition codes
3703    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3704    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3706    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3707    GOTO_OPCODE(ip)                     @ jump to next instruction
3708    /* 10-11 instructions */
3709
3710
3711/* ------------------------------ */
3712    .balign 64
3713.L_OP_INT_TO_FLOAT: /* 0x82 */
3714/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3715/* File: arm-vfp/funop.S */
3716    /*
3717     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3718     * line that specifies an instruction that performs "s1 = op s0".
3719     *
3720     * for: int-to-float, float-to-int
3721     */
3722    /* unop vA, vB */
3723    mov     r3, rINST, lsr #12          @ r3<- B
3724    mov     r9, rINST, lsr #8           @ r9<- A+
3725    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3726    flds    s0, [r3]                    @ s0<- vB
3727    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3728    and     r9, r9, #15                 @ r9<- A
3729    fsitos  s1, s0                              @ s1<- op
3730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3731    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3732    fsts    s1, [r9]                    @ vA<- s1
3733    GOTO_OPCODE(ip)                     @ jump to next instruction
3734
3735
3736/* ------------------------------ */
3737    .balign 64
3738.L_OP_INT_TO_DOUBLE: /* 0x83 */
3739/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3740/* File: arm-vfp/funopWider.S */
3741    /*
3742     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3743     * "instr" line that specifies an instruction that performs "d0 = op s0".
3744     *
3745     * For: int-to-double, float-to-double
3746     */
3747    /* unop vA, vB */
3748    mov     r3, rINST, lsr #12          @ r3<- B
3749    mov     r9, rINST, lsr #8           @ r9<- A+
3750    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3751    flds    s0, [r3]                    @ s0<- vB
3752    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3753    and     r9, r9, #15                 @ r9<- A
3754    fsitod  d0, s0                              @ d0<- op
3755    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3756    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3757    fstd    d0, [r9]                    @ vA<- d0
3758    GOTO_OPCODE(ip)                     @ jump to next instruction
3759
3760
3761/* ------------------------------ */
3762    .balign 64
3763.L_OP_LONG_TO_INT: /* 0x84 */
3764/* File: armv5te/OP_LONG_TO_INT.S */
3765/* we ignore the high word, making this equivalent to a 32-bit reg move */
3766/* File: armv5te/OP_MOVE.S */
3767    /* for move, move-object, long-to-int */
3768    /* op vA, vB */
3769    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3770    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3771    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3772    GET_VREG(r2, r1)                    @ r2<- fp[B]
3773    and     r0, r0, #15
3774    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3775    SET_VREG(r2, r0)                    @ fp[A]<- r2
3776    GOTO_OPCODE(ip)                     @ execute next instruction
3777
3778
3779
3780/* ------------------------------ */
3781    .balign 64
3782.L_OP_LONG_TO_FLOAT: /* 0x85 */
3783/* File: armv5te/OP_LONG_TO_FLOAT.S */
3784/* File: armv5te/unopNarrower.S */
3785    /*
3786     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3787     * that specifies an instruction that performs "result = op r0/r1", where
3788     * "result" is a 32-bit quantity in r0.
3789     *
3790     * For: long-to-float, double-to-int, double-to-float
3791     *
3792     * (This would work for long-to-int, but that instruction is actually
3793     * an exact match for OP_MOVE.)
3794     */
3795    /* unop vA, vB */
3796    mov     r3, rINST, lsr #12          @ r3<- B
3797    mov     r9, rINST, lsr #8           @ r9<- A+
3798    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3799    and     r9, r9, #15
3800    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3801    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3802                               @ optional op; may set condition codes
3803    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3804    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3805    SET_VREG(r0, r9)                    @ vA<- r0
3806    GOTO_OPCODE(ip)                     @ jump to next instruction
3807    /* 10-11 instructions */
3808
3809
3810/* ------------------------------ */
3811    .balign 64
3812.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3813/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3814/* File: armv5te/unopWide.S */
3815    /*
3816     * Generic 64-bit unary operation.  Provide an "instr" line that
3817     * specifies an instruction that performs "result = op r0/r1".
3818     * This could be an ARM instruction or a function call.
3819     *
3820     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3821     */
3822    /* unop vA, vB */
3823    mov     r9, rINST, lsr #8           @ r9<- A+
3824    mov     r3, rINST, lsr #12          @ r3<- B
3825    and     r9, r9, #15
3826    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3827    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3828    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3829    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3830                               @ optional op; may set condition codes
3831    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3833    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3834    GOTO_OPCODE(ip)                     @ jump to next instruction
3835    /* 12-13 instructions */
3836
3837
3838
3839/* ------------------------------ */
3840    .balign 64
3841.L_OP_FLOAT_TO_INT: /* 0x87 */
3842/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3843/* File: arm-vfp/funop.S */
3844    /*
3845     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3846     * line that specifies an instruction that performs "s1 = op s0".
3847     *
3848     * for: int-to-float, float-to-int
3849     */
3850    /* unop vA, vB */
3851    mov     r3, rINST, lsr #12          @ r3<- B
3852    mov     r9, rINST, lsr #8           @ r9<- A+
3853    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3854    flds    s0, [r3]                    @ s0<- vB
3855    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3856    and     r9, r9, #15                 @ r9<- A
3857    ftosizs s1, s0                              @ s1<- op
3858    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3859    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3860    fsts    s1, [r9]                    @ vA<- s1
3861    GOTO_OPCODE(ip)                     @ jump to next instruction
3862
3863
3864/* ------------------------------ */
3865    .balign 64
3866.L_OP_FLOAT_TO_LONG: /* 0x88 */
3867/* File: armv5te/OP_FLOAT_TO_LONG.S */
3868@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3869/* File: armv5te/unopWider.S */
3870    /*
3871     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3872     * that specifies an instruction that performs "result = op r0", where
3873     * "result" is a 64-bit quantity in r0/r1.
3874     *
3875     * For: int-to-long, int-to-double, float-to-long, float-to-double
3876     */
3877    /* unop vA, vB */
3878    mov     r9, rINST, lsr #8           @ r9<- A+
3879    mov     r3, rINST, lsr #12          @ r3<- B
3880    and     r9, r9, #15
3881    GET_VREG(r0, r3)                    @ r0<- vB
3882    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3883                               @ optional op; may set condition codes
3884    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3885    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3887    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3888    GOTO_OPCODE(ip)                     @ jump to next instruction
3889    /* 10-11 instructions */
3890
3891
3892
3893/* ------------------------------ */
3894    .balign 64
3895.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3896/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3897/* File: arm-vfp/funopWider.S */
3898    /*
3899     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3900     * "instr" line that specifies an instruction that performs "d0 = op s0".
3901     *
3902     * For: int-to-double, float-to-double
3903     */
3904    /* unop vA, vB */
3905    mov     r3, rINST, lsr #12          @ r3<- B
3906    mov     r9, rINST, lsr #8           @ r9<- A+
3907    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3908    flds    s0, [r3]                    @ s0<- vB
3909    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3910    and     r9, r9, #15                 @ r9<- A
3911    fcvtds  d0, s0                              @ d0<- op
3912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3913    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3914    fstd    d0, [r9]                    @ vA<- d0
3915    GOTO_OPCODE(ip)                     @ jump to next instruction
3916
3917
3918/* ------------------------------ */
3919    .balign 64
3920.L_OP_DOUBLE_TO_INT: /* 0x8a */
3921/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3922/* File: arm-vfp/funopNarrower.S */
3923    /*
3924     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3925     * "instr" line that specifies an instruction that performs "s0 = op d0".
3926     *
3927     * For: double-to-int, double-to-float
3928     */
3929    /* unop vA, vB */
3930    mov     r3, rINST, lsr #12          @ r3<- B
3931    mov     r9, rINST, lsr #8           @ r9<- A+
3932    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3933    fldd    d0, [r3]                    @ d0<- vB
3934    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3935    and     r9, r9, #15                 @ r9<- A
3936    ftosizd  s0, d0                              @ s0<- op
3937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3938    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3939    fsts    s0, [r9]                    @ vA<- s0
3940    GOTO_OPCODE(ip)                     @ jump to next instruction
3941
3942
3943/* ------------------------------ */
3944    .balign 64
3945.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3946/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3947@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3948/* File: armv5te/unopWide.S */
3949    /*
3950     * Generic 64-bit unary operation.  Provide an "instr" line that
3951     * specifies an instruction that performs "result = op r0/r1".
3952     * This could be an ARM instruction or a function call.
3953     *
3954     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3955     */
3956    /* unop vA, vB */
3957    mov     r9, rINST, lsr #8           @ r9<- A+
3958    mov     r3, rINST, lsr #12          @ r3<- B
3959    and     r9, r9, #15
3960    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3961    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3962    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3963    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3964                               @ optional op; may set condition codes
3965    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3966    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3967    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3968    GOTO_OPCODE(ip)                     @ jump to next instruction
3969    /* 12-13 instructions */
3970
3971
3972
3973
3974/* ------------------------------ */
3975    .balign 64
3976.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3977/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3978/* File: arm-vfp/funopNarrower.S */
3979    /*
3980     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3981     * "instr" line that specifies an instruction that performs "s0 = op d0".
3982     *
3983     * For: double-to-int, double-to-float
3984     */
3985    /* unop vA, vB */
3986    mov     r3, rINST, lsr #12          @ r3<- B
3987    mov     r9, rINST, lsr #8           @ r9<- A+
3988    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3989    fldd    d0, [r3]                    @ d0<- vB
3990    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3991    and     r9, r9, #15                 @ r9<- A
3992    fcvtsd  s0, d0                              @ s0<- op
3993    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3994    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3995    fsts    s0, [r9]                    @ vA<- s0
3996    GOTO_OPCODE(ip)                     @ jump to next instruction
3997
3998
3999/* ------------------------------ */
4000    .balign 64
4001.L_OP_INT_TO_BYTE: /* 0x8d */
4002/* File: armv5te/OP_INT_TO_BYTE.S */
4003/* File: armv5te/unop.S */
4004    /*
4005     * Generic 32-bit unary operation.  Provide an "instr" line that
4006     * specifies an instruction that performs "result = op r0".
4007     * This could be an ARM instruction or a function call.
4008     *
4009     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4010     *      int-to-byte, int-to-char, int-to-short
4011     */
4012    /* unop vA, vB */
4013    mov     r3, rINST, lsr #12          @ r3<- B
4014    mov     r9, rINST, lsr #8           @ r9<- A+
4015    GET_VREG(r0, r3)                    @ r0<- vB
4016    and     r9, r9, #15
4017    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4018    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4019    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4020    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4021    SET_VREG(r0, r9)                    @ vAA<- r0
4022    GOTO_OPCODE(ip)                     @ jump to next instruction
4023    /* 9-10 instructions */
4024
4025
4026/* ------------------------------ */
4027    .balign 64
4028.L_OP_INT_TO_CHAR: /* 0x8e */
4029/* File: armv5te/OP_INT_TO_CHAR.S */
4030/* File: armv5te/unop.S */
4031    /*
4032     * Generic 32-bit unary operation.  Provide an "instr" line that
4033     * specifies an instruction that performs "result = op r0".
4034     * This could be an ARM instruction or a function call.
4035     *
4036     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4037     *      int-to-byte, int-to-char, int-to-short
4038     */
4039    /* unop vA, vB */
4040    mov     r3, rINST, lsr #12          @ r3<- B
4041    mov     r9, rINST, lsr #8           @ r9<- A+
4042    GET_VREG(r0, r3)                    @ r0<- vB
4043    and     r9, r9, #15
4044    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4045    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4046    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4047    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4048    SET_VREG(r0, r9)                    @ vAA<- r0
4049    GOTO_OPCODE(ip)                     @ jump to next instruction
4050    /* 9-10 instructions */
4051
4052
4053/* ------------------------------ */
4054    .balign 64
4055.L_OP_INT_TO_SHORT: /* 0x8f */
4056/* File: armv5te/OP_INT_TO_SHORT.S */
4057/* File: armv5te/unop.S */
4058    /*
4059     * Generic 32-bit unary operation.  Provide an "instr" line that
4060     * specifies an instruction that performs "result = op r0".
4061     * This could be an ARM instruction or a function call.
4062     *
4063     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4064     *      int-to-byte, int-to-char, int-to-short
4065     */
4066    /* unop vA, vB */
4067    mov     r3, rINST, lsr #12          @ r3<- B
4068    mov     r9, rINST, lsr #8           @ r9<- A+
4069    GET_VREG(r0, r3)                    @ r0<- vB
4070    and     r9, r9, #15
4071    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4072    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4073    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4074    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4075    SET_VREG(r0, r9)                    @ vAA<- r0
4076    GOTO_OPCODE(ip)                     @ jump to next instruction
4077    /* 9-10 instructions */
4078
4079
4080/* ------------------------------ */
4081    .balign 64
4082.L_OP_ADD_INT: /* 0x90 */
4083/* File: armv5te/OP_ADD_INT.S */
4084/* File: armv5te/binop.S */
4085    /*
4086     * Generic 32-bit binary operation.  Provide an "instr" line that
4087     * specifies an instruction that performs "result = r0 op r1".
4088     * This could be an ARM instruction or a function call.  (If the result
4089     * comes back in a register other than r0, you can override "result".)
4090     *
4091     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4092     * vCC (r1).  Useful for integer division and modulus.  Note that we
4093     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4094     * handles it correctly.
4095     *
4096     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4097     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4098     *      mul-float, div-float, rem-float
4099     */
4100    /* binop vAA, vBB, vCC */
4101    FETCH(r0, 1)                        @ r0<- CCBB
4102    mov     r9, rINST, lsr #8           @ r9<- AA
4103    mov     r3, r0, lsr #8              @ r3<- CC
4104    and     r2, r0, #255                @ r2<- BB
4105    GET_VREG(r1, r3)                    @ r1<- vCC
4106    GET_VREG(r0, r2)                    @ r0<- vBB
4107    .if 0
4108    cmp     r1, #0                      @ is second operand zero?
4109    beq     common_errDivideByZero
4110    .endif
4111
4112    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4113                               @ optional op; may set condition codes
4114    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4116    SET_VREG(r0, r9)               @ vAA<- r0
4117    GOTO_OPCODE(ip)                     @ jump to next instruction
4118    /* 11-14 instructions */
4119
4120
4121
4122/* ------------------------------ */
4123    .balign 64
4124.L_OP_SUB_INT: /* 0x91 */
4125/* File: armv5te/OP_SUB_INT.S */
4126/* File: armv5te/binop.S */
4127    /*
4128     * Generic 32-bit binary operation.  Provide an "instr" line that
4129     * specifies an instruction that performs "result = r0 op r1".
4130     * This could be an ARM instruction or a function call.  (If the result
4131     * comes back in a register other than r0, you can override "result".)
4132     *
4133     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4134     * vCC (r1).  Useful for integer division and modulus.  Note that we
4135     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4136     * handles it correctly.
4137     *
4138     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4139     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4140     *      mul-float, div-float, rem-float
4141     */
4142    /* binop vAA, vBB, vCC */
4143    FETCH(r0, 1)                        @ r0<- CCBB
4144    mov     r9, rINST, lsr #8           @ r9<- AA
4145    mov     r3, r0, lsr #8              @ r3<- CC
4146    and     r2, r0, #255                @ r2<- BB
4147    GET_VREG(r1, r3)                    @ r1<- vCC
4148    GET_VREG(r0, r2)                    @ r0<- vBB
4149    .if 0
4150    cmp     r1, #0                      @ is second operand zero?
4151    beq     common_errDivideByZero
4152    .endif
4153
4154    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4155                               @ optional op; may set condition codes
4156    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4158    SET_VREG(r0, r9)               @ vAA<- r0
4159    GOTO_OPCODE(ip)                     @ jump to next instruction
4160    /* 11-14 instructions */
4161
4162
4163
4164/* ------------------------------ */
4165    .balign 64
4166.L_OP_MUL_INT: /* 0x92 */
4167/* File: armv5te/OP_MUL_INT.S */
4168/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4169/* File: armv5te/binop.S */
4170    /*
4171     * Generic 32-bit binary operation.  Provide an "instr" line that
4172     * specifies an instruction that performs "result = r0 op r1".
4173     * This could be an ARM instruction or a function call.  (If the result
4174     * comes back in a register other than r0, you can override "result".)
4175     *
4176     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4177     * vCC (r1).  Useful for integer division and modulus.  Note that we
4178     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4179     * handles it correctly.
4180     *
4181     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4182     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4183     *      mul-float, div-float, rem-float
4184     */
4185    /* binop vAA, vBB, vCC */
4186    FETCH(r0, 1)                        @ r0<- CCBB
4187    mov     r9, rINST, lsr #8           @ r9<- AA
4188    mov     r3, r0, lsr #8              @ r3<- CC
4189    and     r2, r0, #255                @ r2<- BB
4190    GET_VREG(r1, r3)                    @ r1<- vCC
4191    GET_VREG(r0, r2)                    @ r0<- vBB
4192    .if 0
4193    cmp     r1, #0                      @ is second operand zero?
4194    beq     common_errDivideByZero
4195    .endif
4196
4197    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4198                               @ optional op; may set condition codes
4199    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4201    SET_VREG(r0, r9)               @ vAA<- r0
4202    GOTO_OPCODE(ip)                     @ jump to next instruction
4203    /* 11-14 instructions */
4204
4205
4206
4207/* ------------------------------ */
4208    .balign 64
4209.L_OP_DIV_INT: /* 0x93 */
4210/* File: armv5te/OP_DIV_INT.S */
4211/* File: armv5te/binop.S */
4212    /*
4213     * Generic 32-bit binary operation.  Provide an "instr" line that
4214     * specifies an instruction that performs "result = r0 op r1".
4215     * This could be an ARM instruction or a function call.  (If the result
4216     * comes back in a register other than r0, you can override "result".)
4217     *
4218     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4219     * vCC (r1).  Useful for integer division and modulus.  Note that we
4220     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4221     * handles it correctly.
4222     *
4223     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4224     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4225     *      mul-float, div-float, rem-float
4226     */
4227    /* binop vAA, vBB, vCC */
4228    FETCH(r0, 1)                        @ r0<- CCBB
4229    mov     r9, rINST, lsr #8           @ r9<- AA
4230    mov     r3, r0, lsr #8              @ r3<- CC
4231    and     r2, r0, #255                @ r2<- BB
4232    GET_VREG(r1, r3)                    @ r1<- vCC
4233    GET_VREG(r0, r2)                    @ r0<- vBB
4234    .if 1
4235    cmp     r1, #0                      @ is second operand zero?
4236    beq     common_errDivideByZero
4237    .endif
4238
4239    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4240                               @ optional op; may set condition codes
4241    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4243    SET_VREG(r0, r9)               @ vAA<- r0
4244    GOTO_OPCODE(ip)                     @ jump to next instruction
4245    /* 11-14 instructions */
4246
4247
4248
4249/* ------------------------------ */
4250    .balign 64
4251.L_OP_REM_INT: /* 0x94 */
4252/* File: armv5te/OP_REM_INT.S */
4253/* idivmod returns quotient in r0 and remainder in r1 */
4254/* File: armv5te/binop.S */
4255    /*
4256     * Generic 32-bit binary operation.  Provide an "instr" line that
4257     * specifies an instruction that performs "result = r0 op r1".
4258     * This could be an ARM instruction or a function call.  (If the result
4259     * comes back in a register other than r0, you can override "result".)
4260     *
4261     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4262     * vCC (r1).  Useful for integer division and modulus.  Note that we
4263     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4264     * handles it correctly.
4265     *
4266     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4267     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4268     *      mul-float, div-float, rem-float
4269     */
4270    /* binop vAA, vBB, vCC */
4271    FETCH(r0, 1)                        @ r0<- CCBB
4272    mov     r9, rINST, lsr #8           @ r9<- AA
4273    mov     r3, r0, lsr #8              @ r3<- CC
4274    and     r2, r0, #255                @ r2<- BB
4275    GET_VREG(r1, r3)                    @ r1<- vCC
4276    GET_VREG(r0, r2)                    @ r0<- vBB
4277    .if 1
4278    cmp     r1, #0                      @ is second operand zero?
4279    beq     common_errDivideByZero
4280    .endif
4281
4282    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4283                               @ optional op; may set condition codes
4284    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4285    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4286    SET_VREG(r1, r9)               @ vAA<- r1
4287    GOTO_OPCODE(ip)                     @ jump to next instruction
4288    /* 11-14 instructions */
4289
4290
4291
4292/* ------------------------------ */
4293    .balign 64
4294.L_OP_AND_INT: /* 0x95 */
4295/* File: armv5te/OP_AND_INT.S */
4296/* File: armv5te/binop.S */
4297    /*
4298     * Generic 32-bit binary operation.  Provide an "instr" line that
4299     * specifies an instruction that performs "result = r0 op r1".
4300     * This could be an ARM instruction or a function call.  (If the result
4301     * comes back in a register other than r0, you can override "result".)
4302     *
4303     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4304     * vCC (r1).  Useful for integer division and modulus.  Note that we
4305     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4306     * handles it correctly.
4307     *
4308     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4309     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4310     *      mul-float, div-float, rem-float
4311     */
4312    /* binop vAA, vBB, vCC */
4313    FETCH(r0, 1)                        @ r0<- CCBB
4314    mov     r9, rINST, lsr #8           @ r9<- AA
4315    mov     r3, r0, lsr #8              @ r3<- CC
4316    and     r2, r0, #255                @ r2<- BB
4317    GET_VREG(r1, r3)                    @ r1<- vCC
4318    GET_VREG(r0, r2)                    @ r0<- vBB
4319    .if 0
4320    cmp     r1, #0                      @ is second operand zero?
4321    beq     common_errDivideByZero
4322    .endif
4323
4324    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4325                               @ optional op; may set condition codes
4326    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4328    SET_VREG(r0, r9)               @ vAA<- r0
4329    GOTO_OPCODE(ip)                     @ jump to next instruction
4330    /* 11-14 instructions */
4331
4332
4333
4334/* ------------------------------ */
4335    .balign 64
4336.L_OP_OR_INT: /* 0x96 */
4337/* File: armv5te/OP_OR_INT.S */
4338/* File: armv5te/binop.S */
4339    /*
4340     * Generic 32-bit binary operation.  Provide an "instr" line that
4341     * specifies an instruction that performs "result = r0 op r1".
4342     * This could be an ARM instruction or a function call.  (If the result
4343     * comes back in a register other than r0, you can override "result".)
4344     *
4345     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4346     * vCC (r1).  Useful for integer division and modulus.  Note that we
4347     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4348     * handles it correctly.
4349     *
4350     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4351     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4352     *      mul-float, div-float, rem-float
4353     */
4354    /* binop vAA, vBB, vCC */
4355    FETCH(r0, 1)                        @ r0<- CCBB
4356    mov     r9, rINST, lsr #8           @ r9<- AA
4357    mov     r3, r0, lsr #8              @ r3<- CC
4358    and     r2, r0, #255                @ r2<- BB
4359    GET_VREG(r1, r3)                    @ r1<- vCC
4360    GET_VREG(r0, r2)                    @ r0<- vBB
4361    .if 0
4362    cmp     r1, #0                      @ is second operand zero?
4363    beq     common_errDivideByZero
4364    .endif
4365
4366    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4367                               @ optional op; may set condition codes
4368    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4369    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4370    SET_VREG(r0, r9)               @ vAA<- r0
4371    GOTO_OPCODE(ip)                     @ jump to next instruction
4372    /* 11-14 instructions */
4373
4374
4375
4376/* ------------------------------ */
4377    .balign 64
4378.L_OP_XOR_INT: /* 0x97 */
4379/* File: armv5te/OP_XOR_INT.S */
4380/* File: armv5te/binop.S */
4381    /*
4382     * Generic 32-bit binary operation.  Provide an "instr" line that
4383     * specifies an instruction that performs "result = r0 op r1".
4384     * This could be an ARM instruction or a function call.  (If the result
4385     * comes back in a register other than r0, you can override "result".)
4386     *
4387     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4388     * vCC (r1).  Useful for integer division and modulus.  Note that we
4389     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4390     * handles it correctly.
4391     *
4392     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4393     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4394     *      mul-float, div-float, rem-float
4395     */
4396    /* binop vAA, vBB, vCC */
4397    FETCH(r0, 1)                        @ r0<- CCBB
4398    mov     r9, rINST, lsr #8           @ r9<- AA
4399    mov     r3, r0, lsr #8              @ r3<- CC
4400    and     r2, r0, #255                @ r2<- BB
4401    GET_VREG(r1, r3)                    @ r1<- vCC
4402    GET_VREG(r0, r2)                    @ r0<- vBB
4403    .if 0
4404    cmp     r1, #0                      @ is second operand zero?
4405    beq     common_errDivideByZero
4406    .endif
4407
4408    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4409                               @ optional op; may set condition codes
4410    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4411    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4412    SET_VREG(r0, r9)               @ vAA<- r0
4413    GOTO_OPCODE(ip)                     @ jump to next instruction
4414    /* 11-14 instructions */
4415
4416
4417
4418/* ------------------------------ */
4419    .balign 64
4420.L_OP_SHL_INT: /* 0x98 */
4421/* File: armv5te/OP_SHL_INT.S */
4422/* File: armv5te/binop.S */
4423    /*
4424     * Generic 32-bit binary operation.  Provide an "instr" line that
4425     * specifies an instruction that performs "result = r0 op r1".
4426     * This could be an ARM instruction or a function call.  (If the result
4427     * comes back in a register other than r0, you can override "result".)
4428     *
4429     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4430     * vCC (r1).  Useful for integer division and modulus.  Note that we
4431     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4432     * handles it correctly.
4433     *
4434     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4435     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4436     *      mul-float, div-float, rem-float
4437     */
4438    /* binop vAA, vBB, vCC */
4439    FETCH(r0, 1)                        @ r0<- CCBB
4440    mov     r9, rINST, lsr #8           @ r9<- AA
4441    mov     r3, r0, lsr #8              @ r3<- CC
4442    and     r2, r0, #255                @ r2<- BB
4443    GET_VREG(r1, r3)                    @ r1<- vCC
4444    GET_VREG(r0, r2)                    @ r0<- vBB
4445    .if 0
4446    cmp     r1, #0                      @ is second operand zero?
4447    beq     common_errDivideByZero
4448    .endif
4449
4450    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4451    and     r1, r1, #31                           @ optional op; may set condition codes
4452    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4453    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4454    SET_VREG(r0, r9)               @ vAA<- r0
4455    GOTO_OPCODE(ip)                     @ jump to next instruction
4456    /* 11-14 instructions */
4457
4458
4459
4460/* ------------------------------ */
4461    .balign 64
4462.L_OP_SHR_INT: /* 0x99 */
4463/* File: armv5te/OP_SHR_INT.S */
4464/* File: armv5te/binop.S */
4465    /*
4466     * Generic 32-bit binary operation.  Provide an "instr" line that
4467     * specifies an instruction that performs "result = r0 op r1".
4468     * This could be an ARM instruction or a function call.  (If the result
4469     * comes back in a register other than r0, you can override "result".)
4470     *
4471     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4472     * vCC (r1).  Useful for integer division and modulus.  Note that we
4473     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4474     * handles it correctly.
4475     *
4476     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4477     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4478     *      mul-float, div-float, rem-float
4479     */
4480    /* binop vAA, vBB, vCC */
4481    FETCH(r0, 1)                        @ r0<- CCBB
4482    mov     r9, rINST, lsr #8           @ r9<- AA
4483    mov     r3, r0, lsr #8              @ r3<- CC
4484    and     r2, r0, #255                @ r2<- BB
4485    GET_VREG(r1, r3)                    @ r1<- vCC
4486    GET_VREG(r0, r2)                    @ r0<- vBB
4487    .if 0
4488    cmp     r1, #0                      @ is second operand zero?
4489    beq     common_errDivideByZero
4490    .endif
4491
4492    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4493    and     r1, r1, #31                           @ optional op; may set condition codes
4494    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4496    SET_VREG(r0, r9)               @ vAA<- r0
4497    GOTO_OPCODE(ip)                     @ jump to next instruction
4498    /* 11-14 instructions */
4499
4500
4501
4502/* ------------------------------ */
4503    .balign 64
4504.L_OP_USHR_INT: /* 0x9a */
4505/* File: armv5te/OP_USHR_INT.S */
4506/* File: armv5te/binop.S */
4507    /*
4508     * Generic 32-bit binary operation.  Provide an "instr" line that
4509     * specifies an instruction that performs "result = r0 op r1".
4510     * This could be an ARM instruction or a function call.  (If the result
4511     * comes back in a register other than r0, you can override "result".)
4512     *
4513     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4514     * vCC (r1).  Useful for integer division and modulus.  Note that we
4515     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4516     * handles it correctly.
4517     *
4518     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4519     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4520     *      mul-float, div-float, rem-float
4521     */
4522    /* binop vAA, vBB, vCC */
4523    FETCH(r0, 1)                        @ r0<- CCBB
4524    mov     r9, rINST, lsr #8           @ r9<- AA
4525    mov     r3, r0, lsr #8              @ r3<- CC
4526    and     r2, r0, #255                @ r2<- BB
4527    GET_VREG(r1, r3)                    @ r1<- vCC
4528    GET_VREG(r0, r2)                    @ r0<- vBB
4529    .if 0
4530    cmp     r1, #0                      @ is second operand zero?
4531    beq     common_errDivideByZero
4532    .endif
4533
4534    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4535    and     r1, r1, #31                           @ optional op; may set condition codes
4536    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4538    SET_VREG(r0, r9)               @ vAA<- r0
4539    GOTO_OPCODE(ip)                     @ jump to next instruction
4540    /* 11-14 instructions */
4541
4542
4543
4544/* ------------------------------ */
4545    .balign 64
4546.L_OP_ADD_LONG: /* 0x9b */
4547/* File: armv5te/OP_ADD_LONG.S */
4548/* File: armv5te/binopWide.S */
4549    /*
4550     * Generic 64-bit binary operation.  Provide an "instr" line that
4551     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4552     * This could be an ARM instruction or a function call.  (If the result
4553     * comes back in a register other than r0, you can override "result".)
4554     *
4555     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4556     * vCC (r1).  Useful for integer division and modulus.
4557     *
4558     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4559     *      xor-long, add-double, sub-double, mul-double, div-double,
4560     *      rem-double
4561     *
4562     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4563     */
4564    /* binop vAA, vBB, vCC */
4565    FETCH(r0, 1)                        @ r0<- CCBB
4566    mov     r9, rINST, lsr #8           @ r9<- AA
4567    and     r2, r0, #255                @ r2<- BB
4568    mov     r3, r0, lsr #8              @ r3<- CC
4569    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4570    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4571    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4572    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4573    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4574    .if 0
4575    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4576    beq     common_errDivideByZero
4577    .endif
4578    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4579
4580    adds    r0, r0, r2                           @ optional op; may set condition codes
4581    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4582    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4583    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4584    GOTO_OPCODE(ip)                     @ jump to next instruction
4585    /* 14-17 instructions */
4586
4587
4588
4589/* ------------------------------ */
4590    .balign 64
4591.L_OP_SUB_LONG: /* 0x9c */
4592/* File: armv5te/OP_SUB_LONG.S */
4593/* File: armv5te/binopWide.S */
4594    /*
4595     * Generic 64-bit binary operation.  Provide an "instr" line that
4596     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4597     * This could be an ARM instruction or a function call.  (If the result
4598     * comes back in a register other than r0, you can override "result".)
4599     *
4600     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4601     * vCC (r1).  Useful for integer division and modulus.
4602     *
4603     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4604     *      xor-long, add-double, sub-double, mul-double, div-double,
4605     *      rem-double
4606     *
4607     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4608     */
4609    /* binop vAA, vBB, vCC */
4610    FETCH(r0, 1)                        @ r0<- CCBB
4611    mov     r9, rINST, lsr #8           @ r9<- AA
4612    and     r2, r0, #255                @ r2<- BB
4613    mov     r3, r0, lsr #8              @ r3<- CC
4614    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4615    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4616    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4617    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4618    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4619    .if 0
4620    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4621    beq     common_errDivideByZero
4622    .endif
4623    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4624
4625    subs    r0, r0, r2                           @ optional op; may set condition codes
4626    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4627    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4628    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4629    GOTO_OPCODE(ip)                     @ jump to next instruction
4630    /* 14-17 instructions */
4631
4632
4633
4634/* ------------------------------ */
4635    .balign 64
4636.L_OP_MUL_LONG: /* 0x9d */
4637/* File: armv5te/OP_MUL_LONG.S */
4638    /*
4639     * Signed 64-bit integer multiply.
4640     *
4641     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4642     *        WX
4643     *      x YZ
4644     *  --------
4645     *     ZW ZX
4646     *  YW YX
4647     *
4648     * The low word of the result holds ZX, the high word holds
4649     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4650     * it doesn't fit in the low 64 bits.
4651     *
4652     * Unlike most ARM math operations, multiply instructions have
4653     * restrictions on using the same register more than once (Rd and Rm
4654     * cannot be the same).
4655     */
4656    /* mul-long vAA, vBB, vCC */
4657    FETCH(r0, 1)                        @ r0<- CCBB
4658    and     r2, r0, #255                @ r2<- BB
4659    mov     r3, r0, lsr #8              @ r3<- CC
4660    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4661    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4662    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4663    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4664    mul     ip, r2, r1                  @  ip<- ZxW
4665    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4666    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4667    mov     r0, rINST, lsr #8           @ r0<- AA
4668    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4669    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4670    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4671    b       .LOP_MUL_LONG_finish
4672
4673/* ------------------------------ */
4674    .balign 64
4675.L_OP_DIV_LONG: /* 0x9e */
4676/* File: armv5te/OP_DIV_LONG.S */
4677/* File: armv5te/binopWide.S */
4678    /*
4679     * Generic 64-bit binary operation.  Provide an "instr" line that
4680     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4681     * This could be an ARM instruction or a function call.  (If the result
4682     * comes back in a register other than r0, you can override "result".)
4683     *
4684     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4685     * vCC (r1).  Useful for integer division and modulus.
4686     *
4687     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4688     *      xor-long, add-double, sub-double, mul-double, div-double,
4689     *      rem-double
4690     *
4691     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4692     */
4693    /* binop vAA, vBB, vCC */
4694    FETCH(r0, 1)                        @ r0<- CCBB
4695    mov     r9, rINST, lsr #8           @ r9<- AA
4696    and     r2, r0, #255                @ r2<- BB
4697    mov     r3, r0, lsr #8              @ r3<- CC
4698    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4699    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4700    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4701    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4702    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4703    .if 1
4704    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4705    beq     common_errDivideByZero
4706    .endif
4707    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4708
4709                               @ optional op; may set condition codes
4710    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4712    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4713    GOTO_OPCODE(ip)                     @ jump to next instruction
4714    /* 14-17 instructions */
4715
4716
4717
4718/* ------------------------------ */
4719    .balign 64
4720.L_OP_REM_LONG: /* 0x9f */
4721/* File: armv5te/OP_REM_LONG.S */
4722/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4723/* File: armv5te/binopWide.S */
4724    /*
4725     * Generic 64-bit binary operation.  Provide an "instr" line that
4726     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4727     * This could be an ARM instruction or a function call.  (If the result
4728     * comes back in a register other than r0, you can override "result".)
4729     *
4730     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4731     * vCC (r1).  Useful for integer division and modulus.
4732     *
4733     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4734     *      xor-long, add-double, sub-double, mul-double, div-double,
4735     *      rem-double
4736     *
4737     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4738     */
4739    /* binop vAA, vBB, vCC */
4740    FETCH(r0, 1)                        @ r0<- CCBB
4741    mov     r9, rINST, lsr #8           @ r9<- AA
4742    and     r2, r0, #255                @ r2<- BB
4743    mov     r3, r0, lsr #8              @ r3<- CC
4744    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4745    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4746    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4747    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4748    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4749    .if 1
4750    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4751    beq     common_errDivideByZero
4752    .endif
4753    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4754
4755                               @ optional op; may set condition codes
4756    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4758    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4759    GOTO_OPCODE(ip)                     @ jump to next instruction
4760    /* 14-17 instructions */
4761
4762
4763
4764/* ------------------------------ */
4765    .balign 64
4766.L_OP_AND_LONG: /* 0xa0 */
4767/* File: armv5te/OP_AND_LONG.S */
4768/* File: armv5te/binopWide.S */
4769    /*
4770     * Generic 64-bit binary operation.  Provide an "instr" line that
4771     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4772     * This could be an ARM instruction or a function call.  (If the result
4773     * comes back in a register other than r0, you can override "result".)
4774     *
4775     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4776     * vCC (r1).  Useful for integer division and modulus.
4777     *
4778     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4779     *      xor-long, add-double, sub-double, mul-double, div-double,
4780     *      rem-double
4781     *
4782     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4783     */
4784    /* binop vAA, vBB, vCC */
4785    FETCH(r0, 1)                        @ r0<- CCBB
4786    mov     r9, rINST, lsr #8           @ r9<- AA
4787    and     r2, r0, #255                @ r2<- BB
4788    mov     r3, r0, lsr #8              @ r3<- CC
4789    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4790    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4791    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4792    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4793    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4794    .if 0
4795    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4796    beq     common_errDivideByZero
4797    .endif
4798    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4799
4800    and     r0, r0, r2                           @ optional op; may set condition codes
4801    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4803    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4804    GOTO_OPCODE(ip)                     @ jump to next instruction
4805    /* 14-17 instructions */
4806
4807
4808
4809/* ------------------------------ */
4810    .balign 64
4811.L_OP_OR_LONG: /* 0xa1 */
4812/* File: armv5te/OP_OR_LONG.S */
4813/* File: armv5te/binopWide.S */
4814    /*
4815     * Generic 64-bit binary operation.  Provide an "instr" line that
4816     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4817     * This could be an ARM instruction or a function call.  (If the result
4818     * comes back in a register other than r0, you can override "result".)
4819     *
4820     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4821     * vCC (r1).  Useful for integer division and modulus.
4822     *
4823     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4824     *      xor-long, add-double, sub-double, mul-double, div-double,
4825     *      rem-double
4826     *
4827     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4828     */
4829    /* binop vAA, vBB, vCC */
4830    FETCH(r0, 1)                        @ r0<- CCBB
4831    mov     r9, rINST, lsr #8           @ r9<- AA
4832    and     r2, r0, #255                @ r2<- BB
4833    mov     r3, r0, lsr #8              @ r3<- CC
4834    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4835    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4836    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4837    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4838    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4839    .if 0
4840    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4841    beq     common_errDivideByZero
4842    .endif
4843    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4844
4845    orr     r0, r0, r2                           @ optional op; may set condition codes
4846    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4848    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4849    GOTO_OPCODE(ip)                     @ jump to next instruction
4850    /* 14-17 instructions */
4851
4852
4853
4854/* ------------------------------ */
4855    .balign 64
4856.L_OP_XOR_LONG: /* 0xa2 */
4857/* File: armv5te/OP_XOR_LONG.S */
4858/* File: armv5te/binopWide.S */
4859    /*
4860     * Generic 64-bit binary operation.  Provide an "instr" line that
4861     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4862     * This could be an ARM instruction or a function call.  (If the result
4863     * comes back in a register other than r0, you can override "result".)
4864     *
4865     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4866     * vCC (r1).  Useful for integer division and modulus.
4867     *
4868     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4869     *      xor-long, add-double, sub-double, mul-double, div-double,
4870     *      rem-double
4871     *
4872     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4873     */
4874    /* binop vAA, vBB, vCC */
4875    FETCH(r0, 1)                        @ r0<- CCBB
4876    mov     r9, rINST, lsr #8           @ r9<- AA
4877    and     r2, r0, #255                @ r2<- BB
4878    mov     r3, r0, lsr #8              @ r3<- CC
4879    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4880    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4881    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4882    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4883    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4884    .if 0
4885    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4886    beq     common_errDivideByZero
4887    .endif
4888    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4889
4890    eor     r0, r0, r2                           @ optional op; may set condition codes
4891    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4892    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4893    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4894    GOTO_OPCODE(ip)                     @ jump to next instruction
4895    /* 14-17 instructions */
4896
4897
4898
4899/* ------------------------------ */
4900    .balign 64
4901.L_OP_SHL_LONG: /* 0xa3 */
4902/* File: armv5te/OP_SHL_LONG.S */
4903    /*
4904     * Long integer shift.  This is different from the generic 32/64-bit
4905     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4906     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4907     * 6 bits of the shift distance.
4908     */
4909    /* shl-long vAA, vBB, vCC */
4910    FETCH(r0, 1)                        @ r0<- CCBB
4911    mov     r9, rINST, lsr #8           @ r9<- AA
4912    and     r3, r0, #255                @ r3<- BB
4913    mov     r0, r0, lsr #8              @ r0<- CC
4914    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4915    GET_VREG(r2, r0)                    @ r2<- vCC
4916    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4917    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4918    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4919
4920    mov     r1, r1, asl r2              @  r1<- r1 << r2
4921    rsb     r3, r2, #32                 @  r3<- 32 - r2
4922    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4923    subs    ip, r2, #32                 @  ip<- r2 - 32
4924    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4925    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4926    b       .LOP_SHL_LONG_finish
4927
4928/* ------------------------------ */
4929    .balign 64
4930.L_OP_SHR_LONG: /* 0xa4 */
4931/* File: armv5te/OP_SHR_LONG.S */
4932    /*
4933     * Long integer shift.  This is different from the generic 32/64-bit
4934     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4935     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4936     * 6 bits of the shift distance.
4937     */
4938    /* shr-long vAA, vBB, vCC */
4939    FETCH(r0, 1)                        @ r0<- CCBB
4940    mov     r9, rINST, lsr #8           @ r9<- AA
4941    and     r3, r0, #255                @ r3<- BB
4942    mov     r0, r0, lsr #8              @ r0<- CC
4943    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4944    GET_VREG(r2, r0)                    @ r2<- vCC
4945    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4946    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4947    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4948
4949    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4950    rsb     r3, r2, #32                 @  r3<- 32 - r2
4951    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4952    subs    ip, r2, #32                 @  ip<- r2 - 32
4953    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4954    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4955    b       .LOP_SHR_LONG_finish
4956
4957/* ------------------------------ */
4958    .balign 64
4959.L_OP_USHR_LONG: /* 0xa5 */
4960/* File: armv5te/OP_USHR_LONG.S */
4961    /*
4962     * Long integer shift.  This is different from the generic 32/64-bit
4963     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4964     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4965     * 6 bits of the shift distance.
4966     */
4967    /* ushr-long vAA, vBB, vCC */
4968    FETCH(r0, 1)                        @ r0<- CCBB
4969    mov     r9, rINST, lsr #8           @ r9<- AA
4970    and     r3, r0, #255                @ r3<- BB
4971    mov     r0, r0, lsr #8              @ r0<- CC
4972    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4973    GET_VREG(r2, r0)                    @ r2<- vCC
4974    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4975    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4976    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4977
4978    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4979    rsb     r3, r2, #32                 @  r3<- 32 - r2
4980    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4981    subs    ip, r2, #32                 @  ip<- r2 - 32
4982    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4983    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4984    b       .LOP_USHR_LONG_finish
4985
4986/* ------------------------------ */
4987    .balign 64
4988.L_OP_ADD_FLOAT: /* 0xa6 */
4989/* File: arm-vfp/OP_ADD_FLOAT.S */
4990/* File: arm-vfp/fbinop.S */
4991    /*
4992     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4993     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4994     * use the "softfp" ABI, this must be an instruction, not a function call.
4995     *
4996     * For: add-float, sub-float, mul-float, div-float
4997     */
4998    /* floatop vAA, vBB, vCC */
4999    FETCH(r0, 1)                        @ r0<- CCBB
5000    mov     r9, rINST, lsr #8           @ r9<- AA
5001    mov     r3, r0, lsr #8              @ r3<- CC
5002    and     r2, r0, #255                @ r2<- BB
5003    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5004    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5005    flds    s1, [r3]                    @ s1<- vCC
5006    flds    s0, [r2]                    @ s0<- vBB
5007
5008    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5009    fadds   s2, s0, s1                              @ s2<- op
5010    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5011    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5012    fsts    s2, [r9]                    @ vAA<- s2
5013    GOTO_OPCODE(ip)                     @ jump to next instruction
5014
5015
5016/* ------------------------------ */
5017    .balign 64
5018.L_OP_SUB_FLOAT: /* 0xa7 */
5019/* File: arm-vfp/OP_SUB_FLOAT.S */
5020/* File: arm-vfp/fbinop.S */
5021    /*
5022     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5023     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5024     * use the "softfp" ABI, this must be an instruction, not a function call.
5025     *
5026     * For: add-float, sub-float, mul-float, div-float
5027     */
5028    /* floatop vAA, vBB, vCC */
5029    FETCH(r0, 1)                        @ r0<- CCBB
5030    mov     r9, rINST, lsr #8           @ r9<- AA
5031    mov     r3, r0, lsr #8              @ r3<- CC
5032    and     r2, r0, #255                @ r2<- BB
5033    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5034    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5035    flds    s1, [r3]                    @ s1<- vCC
5036    flds    s0, [r2]                    @ s0<- vBB
5037
5038    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5039    fsubs   s2, s0, s1                              @ s2<- op
5040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5041    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5042    fsts    s2, [r9]                    @ vAA<- s2
5043    GOTO_OPCODE(ip)                     @ jump to next instruction
5044
5045
5046/* ------------------------------ */
5047    .balign 64
5048.L_OP_MUL_FLOAT: /* 0xa8 */
5049/* File: arm-vfp/OP_MUL_FLOAT.S */
5050/* File: arm-vfp/fbinop.S */
5051    /*
5052     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5053     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5054     * use the "softfp" ABI, this must be an instruction, not a function call.
5055     *
5056     * For: add-float, sub-float, mul-float, div-float
5057     */
5058    /* floatop vAA, vBB, vCC */
5059    FETCH(r0, 1)                        @ r0<- CCBB
5060    mov     r9, rINST, lsr #8           @ r9<- AA
5061    mov     r3, r0, lsr #8              @ r3<- CC
5062    and     r2, r0, #255                @ r2<- BB
5063    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5064    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5065    flds    s1, [r3]                    @ s1<- vCC
5066    flds    s0, [r2]                    @ s0<- vBB
5067
5068    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5069    fmuls   s2, s0, s1                              @ s2<- op
5070    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5071    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5072    fsts    s2, [r9]                    @ vAA<- s2
5073    GOTO_OPCODE(ip)                     @ jump to next instruction
5074
5075
5076/* ------------------------------ */
5077    .balign 64
5078.L_OP_DIV_FLOAT: /* 0xa9 */
5079/* File: arm-vfp/OP_DIV_FLOAT.S */
5080/* File: arm-vfp/fbinop.S */
5081    /*
5082     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5083     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5084     * use the "softfp" ABI, this must be an instruction, not a function call.
5085     *
5086     * For: add-float, sub-float, mul-float, div-float
5087     */
5088    /* floatop vAA, vBB, vCC */
5089    FETCH(r0, 1)                        @ r0<- CCBB
5090    mov     r9, rINST, lsr #8           @ r9<- AA
5091    mov     r3, r0, lsr #8              @ r3<- CC
5092    and     r2, r0, #255                @ r2<- BB
5093    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5094    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5095    flds    s1, [r3]                    @ s1<- vCC
5096    flds    s0, [r2]                    @ s0<- vBB
5097
5098    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5099    fdivs   s2, s0, s1                              @ s2<- op
5100    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5101    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5102    fsts    s2, [r9]                    @ vAA<- s2
5103    GOTO_OPCODE(ip)                     @ jump to next instruction
5104
5105
5106/* ------------------------------ */
5107    .balign 64
5108.L_OP_REM_FLOAT: /* 0xaa */
5109/* File: armv5te/OP_REM_FLOAT.S */
5110/* EABI doesn't define a float remainder function, but libm does */
5111/* File: armv5te/binop.S */
5112    /*
5113     * Generic 32-bit binary operation.  Provide an "instr" line that
5114     * specifies an instruction that performs "result = r0 op r1".
5115     * This could be an ARM instruction or a function call.  (If the result
5116     * comes back in a register other than r0, you can override "result".)
5117     *
5118     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5119     * vCC (r1).  Useful for integer division and modulus.  Note that we
5120     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5121     * handles it correctly.
5122     *
5123     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5124     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5125     *      mul-float, div-float, rem-float
5126     */
5127    /* binop vAA, vBB, vCC */
5128    FETCH(r0, 1)                        @ r0<- CCBB
5129    mov     r9, rINST, lsr #8           @ r9<- AA
5130    mov     r3, r0, lsr #8              @ r3<- CC
5131    and     r2, r0, #255                @ r2<- BB
5132    GET_VREG(r1, r3)                    @ r1<- vCC
5133    GET_VREG(r0, r2)                    @ r0<- vBB
5134    .if 0
5135    cmp     r1, #0                      @ is second operand zero?
5136    beq     common_errDivideByZero
5137    .endif
5138
5139    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5140                               @ optional op; may set condition codes
5141    bl      fmodf                              @ r0<- op, r0-r3 changed
5142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5143    SET_VREG(r0, r9)               @ vAA<- r0
5144    GOTO_OPCODE(ip)                     @ jump to next instruction
5145    /* 11-14 instructions */
5146
5147
5148
5149/* ------------------------------ */
5150    .balign 64
5151.L_OP_ADD_DOUBLE: /* 0xab */
5152/* File: arm-vfp/OP_ADD_DOUBLE.S */
5153/* File: arm-vfp/fbinopWide.S */
5154    /*
5155     * Generic 64-bit double-precision floating point binary operation.
5156     * Provide an "instr" line that specifies an instruction that performs
5157     * "d2 = d0 op d1".
5158     *
5159     * for: add-double, sub-double, mul-double, div-double
5160     */
5161    /* doubleop vAA, vBB, vCC */
5162    FETCH(r0, 1)                        @ r0<- CCBB
5163    mov     r9, rINST, lsr #8           @ r9<- AA
5164    mov     r3, r0, lsr #8              @ r3<- CC
5165    and     r2, r0, #255                @ r2<- BB
5166    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5167    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5168    fldd    d1, [r3]                    @ d1<- vCC
5169    fldd    d0, [r2]                    @ d0<- vBB
5170
5171    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5172    faddd   d2, d0, d1                              @ s2<- op
5173    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5174    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5175    fstd    d2, [r9]                    @ vAA<- d2
5176    GOTO_OPCODE(ip)                     @ jump to next instruction
5177
5178
5179/* ------------------------------ */
5180    .balign 64
5181.L_OP_SUB_DOUBLE: /* 0xac */
5182/* File: arm-vfp/OP_SUB_DOUBLE.S */
5183/* File: arm-vfp/fbinopWide.S */
5184    /*
5185     * Generic 64-bit double-precision floating point binary operation.
5186     * Provide an "instr" line that specifies an instruction that performs
5187     * "d2 = d0 op d1".
5188     *
5189     * for: add-double, sub-double, mul-double, div-double
5190     */
5191    /* doubleop vAA, vBB, vCC */
5192    FETCH(r0, 1)                        @ r0<- CCBB
5193    mov     r9, rINST, lsr #8           @ r9<- AA
5194    mov     r3, r0, lsr #8              @ r3<- CC
5195    and     r2, r0, #255                @ r2<- BB
5196    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5197    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5198    fldd    d1, [r3]                    @ d1<- vCC
5199    fldd    d0, [r2]                    @ d0<- vBB
5200
5201    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5202    fsubd   d2, d0, d1                              @ s2<- op
5203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5204    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5205    fstd    d2, [r9]                    @ vAA<- d2
5206    GOTO_OPCODE(ip)                     @ jump to next instruction
5207
5208
5209/* ------------------------------ */
5210    .balign 64
5211.L_OP_MUL_DOUBLE: /* 0xad */
5212/* File: arm-vfp/OP_MUL_DOUBLE.S */
5213/* File: arm-vfp/fbinopWide.S */
5214    /*
5215     * Generic 64-bit double-precision floating point binary operation.
5216     * Provide an "instr" line that specifies an instruction that performs
5217     * "d2 = d0 op d1".
5218     *
5219     * for: add-double, sub-double, mul-double, div-double
5220     */
5221    /* doubleop vAA, vBB, vCC */
5222    FETCH(r0, 1)                        @ r0<- CCBB
5223    mov     r9, rINST, lsr #8           @ r9<- AA
5224    mov     r3, r0, lsr #8              @ r3<- CC
5225    and     r2, r0, #255                @ r2<- BB
5226    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5227    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5228    fldd    d1, [r3]                    @ d1<- vCC
5229    fldd    d0, [r2]                    @ d0<- vBB
5230
5231    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5232    fmuld   d2, d0, d1                              @ s2<- op
5233    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5234    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5235    fstd    d2, [r9]                    @ vAA<- d2
5236    GOTO_OPCODE(ip)                     @ jump to next instruction
5237
5238
5239/* ------------------------------ */
5240    .balign 64
5241.L_OP_DIV_DOUBLE: /* 0xae */
5242/* File: arm-vfp/OP_DIV_DOUBLE.S */
5243/* File: arm-vfp/fbinopWide.S */
5244    /*
5245     * Generic 64-bit double-precision floating point binary operation.
5246     * Provide an "instr" line that specifies an instruction that performs
5247     * "d2 = d0 op d1".
5248     *
5249     * for: add-double, sub-double, mul-double, div-double
5250     */
5251    /* doubleop vAA, vBB, vCC */
5252    FETCH(r0, 1)                        @ r0<- CCBB
5253    mov     r9, rINST, lsr #8           @ r9<- AA
5254    mov     r3, r0, lsr #8              @ r3<- CC
5255    and     r2, r0, #255                @ r2<- BB
5256    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5257    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5258    fldd    d1, [r3]                    @ d1<- vCC
5259    fldd    d0, [r2]                    @ d0<- vBB
5260
5261    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5262    fdivd   d2, d0, d1                              @ s2<- op
5263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5264    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5265    fstd    d2, [r9]                    @ vAA<- d2
5266    GOTO_OPCODE(ip)                     @ jump to next instruction
5267
5268
5269/* ------------------------------ */
5270    .balign 64
5271.L_OP_REM_DOUBLE: /* 0xaf */
5272/* File: armv5te/OP_REM_DOUBLE.S */
5273/* EABI doesn't define a double remainder function, but libm does */
5274/* File: armv5te/binopWide.S */
5275    /*
5276     * Generic 64-bit binary operation.  Provide an "instr" line that
5277     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5278     * This could be an ARM instruction or a function call.  (If the result
5279     * comes back in a register other than r0, you can override "result".)
5280     *
5281     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5282     * vCC (r1).  Useful for integer division and modulus.
5283     *
5284     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5285     *      xor-long, add-double, sub-double, mul-double, div-double,
5286     *      rem-double
5287     *
5288     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5289     */
5290    /* binop vAA, vBB, vCC */
5291    FETCH(r0, 1)                        @ r0<- CCBB
5292    mov     r9, rINST, lsr #8           @ r9<- AA
5293    and     r2, r0, #255                @ r2<- BB
5294    mov     r3, r0, lsr #8              @ r3<- CC
5295    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5296    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5297    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5298    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5299    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5300    .if 0
5301    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5302    beq     common_errDivideByZero
5303    .endif
5304    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5305
5306                               @ optional op; may set condition codes
5307    bl      fmod                              @ result<- op, r0-r3 changed
5308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5309    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5310    GOTO_OPCODE(ip)                     @ jump to next instruction
5311    /* 14-17 instructions */
5312
5313
5314
5315/* ------------------------------ */
5316    .balign 64
5317.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5318/* File: armv5te/OP_ADD_INT_2ADDR.S */
5319/* File: armv5te/binop2addr.S */
5320    /*
5321     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5322     * that specifies an instruction that performs "result = r0 op r1".
5323     * This could be an ARM instruction or a function call.  (If the result
5324     * comes back in a register other than r0, you can override "result".)
5325     *
5326     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5327     * vCC (r1).  Useful for integer division and modulus.
5328     *
5329     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5330     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5331     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5332     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5333     */
5334    /* binop/2addr vA, vB */
5335    mov     r9, rINST, lsr #8           @ r9<- A+
5336    mov     r3, rINST, lsr #12          @ r3<- B
5337    and     r9, r9, #15
5338    GET_VREG(r1, r3)                    @ r1<- vB
5339    GET_VREG(r0, r9)                    @ r0<- vA
5340    .if 0
5341    cmp     r1, #0                      @ is second operand zero?
5342    beq     common_errDivideByZero
5343    .endif
5344    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5345
5346                               @ optional op; may set condition codes
5347    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5349    SET_VREG(r0, r9)               @ vAA<- r0
5350    GOTO_OPCODE(ip)                     @ jump to next instruction
5351    /* 10-13 instructions */
5352
5353
5354
5355/* ------------------------------ */
5356    .balign 64
5357.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5358/* File: armv5te/OP_SUB_INT_2ADDR.S */
5359/* File: armv5te/binop2addr.S */
5360    /*
5361     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5362     * that specifies an instruction that performs "result = r0 op r1".
5363     * This could be an ARM instruction or a function call.  (If the result
5364     * comes back in a register other than r0, you can override "result".)
5365     *
5366     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5367     * vCC (r1).  Useful for integer division and modulus.
5368     *
5369     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5370     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5371     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5372     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5373     */
5374    /* binop/2addr vA, vB */
5375    mov     r9, rINST, lsr #8           @ r9<- A+
5376    mov     r3, rINST, lsr #12          @ r3<- B
5377    and     r9, r9, #15
5378    GET_VREG(r1, r3)                    @ r1<- vB
5379    GET_VREG(r0, r9)                    @ r0<- vA
5380    .if 0
5381    cmp     r1, #0                      @ is second operand zero?
5382    beq     common_errDivideByZero
5383    .endif
5384    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5385
5386                               @ optional op; may set condition codes
5387    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5389    SET_VREG(r0, r9)               @ vAA<- r0
5390    GOTO_OPCODE(ip)                     @ jump to next instruction
5391    /* 10-13 instructions */
5392
5393
5394
5395/* ------------------------------ */
5396    .balign 64
5397.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5398/* File: armv5te/OP_MUL_INT_2ADDR.S */
5399/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5400/* File: armv5te/binop2addr.S */
5401    /*
5402     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5403     * that specifies an instruction that performs "result = r0 op r1".
5404     * This could be an ARM instruction or a function call.  (If the result
5405     * comes back in a register other than r0, you can override "result".)
5406     *
5407     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5408     * vCC (r1).  Useful for integer division and modulus.
5409     *
5410     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5411     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5412     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5413     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5414     */
5415    /* binop/2addr vA, vB */
5416    mov     r9, rINST, lsr #8           @ r9<- A+
5417    mov     r3, rINST, lsr #12          @ r3<- B
5418    and     r9, r9, #15
5419    GET_VREG(r1, r3)                    @ r1<- vB
5420    GET_VREG(r0, r9)                    @ r0<- vA
5421    .if 0
5422    cmp     r1, #0                      @ is second operand zero?
5423    beq     common_errDivideByZero
5424    .endif
5425    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5426
5427                               @ optional op; may set condition codes
5428    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5429    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5430    SET_VREG(r0, r9)               @ vAA<- r0
5431    GOTO_OPCODE(ip)                     @ jump to next instruction
5432    /* 10-13 instructions */
5433
5434
5435
5436/* ------------------------------ */
5437    .balign 64
5438.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5439/* File: armv5te/OP_DIV_INT_2ADDR.S */
5440/* File: armv5te/binop2addr.S */
5441    /*
5442     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5443     * that specifies an instruction that performs "result = r0 op r1".
5444     * This could be an ARM instruction or a function call.  (If the result
5445     * comes back in a register other than r0, you can override "result".)
5446     *
5447     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5448     * vCC (r1).  Useful for integer division and modulus.
5449     *
5450     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5451     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5452     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5453     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5454     */
5455    /* binop/2addr vA, vB */
5456    mov     r9, rINST, lsr #8           @ r9<- A+
5457    mov     r3, rINST, lsr #12          @ r3<- B
5458    and     r9, r9, #15
5459    GET_VREG(r1, r3)                    @ r1<- vB
5460    GET_VREG(r0, r9)                    @ r0<- vA
5461    .if 1
5462    cmp     r1, #0                      @ is second operand zero?
5463    beq     common_errDivideByZero
5464    .endif
5465    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5466
5467                               @ optional op; may set condition codes
5468    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5469    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5470    SET_VREG(r0, r9)               @ vAA<- r0
5471    GOTO_OPCODE(ip)                     @ jump to next instruction
5472    /* 10-13 instructions */
5473
5474
5475
5476/* ------------------------------ */
5477    .balign 64
5478.L_OP_REM_INT_2ADDR: /* 0xb4 */
5479/* File: armv5te/OP_REM_INT_2ADDR.S */
5480/* idivmod returns quotient in r0 and remainder in r1 */
5481/* File: armv5te/binop2addr.S */
5482    /*
5483     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5484     * that specifies an instruction that performs "result = r0 op r1".
5485     * This could be an ARM instruction or a function call.  (If the result
5486     * comes back in a register other than r0, you can override "result".)
5487     *
5488     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5489     * vCC (r1).  Useful for integer division and modulus.
5490     *
5491     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5492     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5493     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5494     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5495     */
5496    /* binop/2addr vA, vB */
5497    mov     r9, rINST, lsr #8           @ r9<- A+
5498    mov     r3, rINST, lsr #12          @ r3<- B
5499    and     r9, r9, #15
5500    GET_VREG(r1, r3)                    @ r1<- vB
5501    GET_VREG(r0, r9)                    @ r0<- vA
5502    .if 1
5503    cmp     r1, #0                      @ is second operand zero?
5504    beq     common_errDivideByZero
5505    .endif
5506    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5507
5508                               @ optional op; may set condition codes
5509    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5510    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5511    SET_VREG(r1, r9)               @ vAA<- r1
5512    GOTO_OPCODE(ip)                     @ jump to next instruction
5513    /* 10-13 instructions */
5514
5515
5516
5517/* ------------------------------ */
5518    .balign 64
5519.L_OP_AND_INT_2ADDR: /* 0xb5 */
5520/* File: armv5te/OP_AND_INT_2ADDR.S */
5521/* File: armv5te/binop2addr.S */
5522    /*
5523     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5524     * that specifies an instruction that performs "result = r0 op r1".
5525     * This could be an ARM instruction or a function call.  (If the result
5526     * comes back in a register other than r0, you can override "result".)
5527     *
5528     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5529     * vCC (r1).  Useful for integer division and modulus.
5530     *
5531     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5532     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5533     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5534     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5535     */
5536    /* binop/2addr vA, vB */
5537    mov     r9, rINST, lsr #8           @ r9<- A+
5538    mov     r3, rINST, lsr #12          @ r3<- B
5539    and     r9, r9, #15
5540    GET_VREG(r1, r3)                    @ r1<- vB
5541    GET_VREG(r0, r9)                    @ r0<- vA
5542    .if 0
5543    cmp     r1, #0                      @ is second operand zero?
5544    beq     common_errDivideByZero
5545    .endif
5546    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5547
5548                               @ optional op; may set condition codes
5549    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5550    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5551    SET_VREG(r0, r9)               @ vAA<- r0
5552    GOTO_OPCODE(ip)                     @ jump to next instruction
5553    /* 10-13 instructions */
5554
5555
5556
5557/* ------------------------------ */
5558    .balign 64
5559.L_OP_OR_INT_2ADDR: /* 0xb6 */
5560/* File: armv5te/OP_OR_INT_2ADDR.S */
5561/* File: armv5te/binop2addr.S */
5562    /*
5563     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5564     * that specifies an instruction that performs "result = r0 op r1".
5565     * This could be an ARM instruction or a function call.  (If the result
5566     * comes back in a register other than r0, you can override "result".)
5567     *
5568     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5569     * vCC (r1).  Useful for integer division and modulus.
5570     *
5571     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5572     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5573     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5574     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5575     */
5576    /* binop/2addr vA, vB */
5577    mov     r9, rINST, lsr #8           @ r9<- A+
5578    mov     r3, rINST, lsr #12          @ r3<- B
5579    and     r9, r9, #15
5580    GET_VREG(r1, r3)                    @ r1<- vB
5581    GET_VREG(r0, r9)                    @ r0<- vA
5582    .if 0
5583    cmp     r1, #0                      @ is second operand zero?
5584    beq     common_errDivideByZero
5585    .endif
5586    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5587
5588                               @ optional op; may set condition codes
5589    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5591    SET_VREG(r0, r9)               @ vAA<- r0
5592    GOTO_OPCODE(ip)                     @ jump to next instruction
5593    /* 10-13 instructions */
5594
5595
5596
5597/* ------------------------------ */
5598    .balign 64
5599.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5600/* File: armv5te/OP_XOR_INT_2ADDR.S */
5601/* File: armv5te/binop2addr.S */
5602    /*
5603     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5604     * that specifies an instruction that performs "result = r0 op r1".
5605     * This could be an ARM instruction or a function call.  (If the result
5606     * comes back in a register other than r0, you can override "result".)
5607     *
5608     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5609     * vCC (r1).  Useful for integer division and modulus.
5610     *
5611     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5612     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5613     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5614     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5615     */
5616    /* binop/2addr vA, vB */
5617    mov     r9, rINST, lsr #8           @ r9<- A+
5618    mov     r3, rINST, lsr #12          @ r3<- B
5619    and     r9, r9, #15
5620    GET_VREG(r1, r3)                    @ r1<- vB
5621    GET_VREG(r0, r9)                    @ r0<- vA
5622    .if 0
5623    cmp     r1, #0                      @ is second operand zero?
5624    beq     common_errDivideByZero
5625    .endif
5626    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5627
5628                               @ optional op; may set condition codes
5629    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5630    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5631    SET_VREG(r0, r9)               @ vAA<- r0
5632    GOTO_OPCODE(ip)                     @ jump to next instruction
5633    /* 10-13 instructions */
5634
5635
5636
5637/* ------------------------------ */
5638    .balign 64
5639.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5640/* File: armv5te/OP_SHL_INT_2ADDR.S */
5641/* File: armv5te/binop2addr.S */
5642    /*
5643     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5644     * that specifies an instruction that performs "result = r0 op r1".
5645     * This could be an ARM instruction or a function call.  (If the result
5646     * comes back in a register other than r0, you can override "result".)
5647     *
5648     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5649     * vCC (r1).  Useful for integer division and modulus.
5650     *
5651     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5652     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5653     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5654     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5655     */
5656    /* binop/2addr vA, vB */
5657    mov     r9, rINST, lsr #8           @ r9<- A+
5658    mov     r3, rINST, lsr #12          @ r3<- B
5659    and     r9, r9, #15
5660    GET_VREG(r1, r3)                    @ r1<- vB
5661    GET_VREG(r0, r9)                    @ r0<- vA
5662    .if 0
5663    cmp     r1, #0                      @ is second operand zero?
5664    beq     common_errDivideByZero
5665    .endif
5666    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5667
5668    and     r1, r1, #31                           @ optional op; may set condition codes
5669    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5670    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5671    SET_VREG(r0, r9)               @ vAA<- r0
5672    GOTO_OPCODE(ip)                     @ jump to next instruction
5673    /* 10-13 instructions */
5674
5675
5676
5677/* ------------------------------ */
5678    .balign 64
5679.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5680/* File: armv5te/OP_SHR_INT_2ADDR.S */
5681/* File: armv5te/binop2addr.S */
5682    /*
5683     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5684     * that specifies an instruction that performs "result = r0 op r1".
5685     * This could be an ARM instruction or a function call.  (If the result
5686     * comes back in a register other than r0, you can override "result".)
5687     *
5688     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5689     * vCC (r1).  Useful for integer division and modulus.
5690     *
5691     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5692     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5693     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5694     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5695     */
5696    /* binop/2addr vA, vB */
5697    mov     r9, rINST, lsr #8           @ r9<- A+
5698    mov     r3, rINST, lsr #12          @ r3<- B
5699    and     r9, r9, #15
5700    GET_VREG(r1, r3)                    @ r1<- vB
5701    GET_VREG(r0, r9)                    @ r0<- vA
5702    .if 0
5703    cmp     r1, #0                      @ is second operand zero?
5704    beq     common_errDivideByZero
5705    .endif
5706    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5707
5708    and     r1, r1, #31                           @ optional op; may set condition codes
5709    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5710    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5711    SET_VREG(r0, r9)               @ vAA<- r0
5712    GOTO_OPCODE(ip)                     @ jump to next instruction
5713    /* 10-13 instructions */
5714
5715
5716
5717/* ------------------------------ */
5718    .balign 64
5719.L_OP_USHR_INT_2ADDR: /* 0xba */
5720/* File: armv5te/OP_USHR_INT_2ADDR.S */
5721/* File: armv5te/binop2addr.S */
5722    /*
5723     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5724     * that specifies an instruction that performs "result = r0 op r1".
5725     * This could be an ARM instruction or a function call.  (If the result
5726     * comes back in a register other than r0, you can override "result".)
5727     *
5728     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5729     * vCC (r1).  Useful for integer division and modulus.
5730     *
5731     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5732     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5733     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5734     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5735     */
5736    /* binop/2addr vA, vB */
5737    mov     r9, rINST, lsr #8           @ r9<- A+
5738    mov     r3, rINST, lsr #12          @ r3<- B
5739    and     r9, r9, #15
5740    GET_VREG(r1, r3)                    @ r1<- vB
5741    GET_VREG(r0, r9)                    @ r0<- vA
5742    .if 0
5743    cmp     r1, #0                      @ is second operand zero?
5744    beq     common_errDivideByZero
5745    .endif
5746    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5747
5748    and     r1, r1, #31                           @ optional op; may set condition codes
5749    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5751    SET_VREG(r0, r9)               @ vAA<- r0
5752    GOTO_OPCODE(ip)                     @ jump to next instruction
5753    /* 10-13 instructions */
5754
5755
5756
5757/* ------------------------------ */
5758    .balign 64
5759.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5760/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5761/* File: armv5te/binopWide2addr.S */
5762    /*
5763     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5764     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5765     * This could be an ARM instruction or a function call.  (If the result
5766     * comes back in a register other than r0, you can override "result".)
5767     *
5768     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5769     * vCC (r1).  Useful for integer division and modulus.
5770     *
5771     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5772     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5773     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5774     *      rem-double/2addr
5775     */
5776    /* binop/2addr vA, vB */
5777    mov     r9, rINST, lsr #8           @ r9<- A+
5778    mov     r1, rINST, lsr #12          @ r1<- B
5779    and     r9, r9, #15
5780    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5781    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5782    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5783    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5784    .if 0
5785    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5786    beq     common_errDivideByZero
5787    .endif
5788    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5789
5790    adds    r0, r0, r2                           @ optional op; may set condition codes
5791    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5793    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5794    GOTO_OPCODE(ip)                     @ jump to next instruction
5795    /* 12-15 instructions */
5796
5797
5798
5799/* ------------------------------ */
5800    .balign 64
5801.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5802/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5803/* File: armv5te/binopWide2addr.S */
5804    /*
5805     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5806     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5807     * This could be an ARM instruction or a function call.  (If the result
5808     * comes back in a register other than r0, you can override "result".)
5809     *
5810     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5811     * vCC (r1).  Useful for integer division and modulus.
5812     *
5813     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5814     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5815     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5816     *      rem-double/2addr
5817     */
5818    /* binop/2addr vA, vB */
5819    mov     r9, rINST, lsr #8           @ r9<- A+
5820    mov     r1, rINST, lsr #12          @ r1<- B
5821    and     r9, r9, #15
5822    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5823    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5824    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5825    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5826    .if 0
5827    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5828    beq     common_errDivideByZero
5829    .endif
5830    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5831
5832    subs    r0, r0, r2                           @ optional op; may set condition codes
5833    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5834    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5835    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5836    GOTO_OPCODE(ip)                     @ jump to next instruction
5837    /* 12-15 instructions */
5838
5839
5840
5841/* ------------------------------ */
5842    .balign 64
5843.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5844/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5845    /*
5846     * Signed 64-bit integer multiply, "/2addr" version.
5847     *
5848     * See OP_MUL_LONG for an explanation.
5849     *
5850     * We get a little tight on registers, so to avoid looking up &fp[A]
5851     * again we stuff it into rINST.
5852     */
5853    /* mul-long/2addr vA, vB */
5854    mov     r9, rINST, lsr #8           @ r9<- A+
5855    mov     r1, rINST, lsr #12          @ r1<- B
5856    and     r9, r9, #15
5857    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5858    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5859    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5860    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5861    mul     ip, r2, r1                  @  ip<- ZxW
5862    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5863    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5864    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5865    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5866    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5867    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5868    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5869    GOTO_OPCODE(ip)                     @ jump to next instruction
5870
5871
5872/* ------------------------------ */
5873    .balign 64
5874.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5875/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5876/* File: armv5te/binopWide2addr.S */
5877    /*
5878     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5879     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5880     * This could be an ARM instruction or a function call.  (If the result
5881     * comes back in a register other than r0, you can override "result".)
5882     *
5883     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5884     * vCC (r1).  Useful for integer division and modulus.
5885     *
5886     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5887     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5888     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5889     *      rem-double/2addr
5890     */
5891    /* binop/2addr vA, vB */
5892    mov     r9, rINST, lsr #8           @ r9<- A+
5893    mov     r1, rINST, lsr #12          @ r1<- B
5894    and     r9, r9, #15
5895    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5896    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5897    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5898    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5899    .if 1
5900    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5901    beq     common_errDivideByZero
5902    .endif
5903    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5904
5905                               @ optional op; may set condition codes
5906    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5908    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5909    GOTO_OPCODE(ip)                     @ jump to next instruction
5910    /* 12-15 instructions */
5911
5912
5913
5914/* ------------------------------ */
5915    .balign 64
5916.L_OP_REM_LONG_2ADDR: /* 0xbf */
5917/* File: armv5te/OP_REM_LONG_2ADDR.S */
5918/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5919/* File: armv5te/binopWide2addr.S */
5920    /*
5921     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5922     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5923     * This could be an ARM instruction or a function call.  (If the result
5924     * comes back in a register other than r0, you can override "result".)
5925     *
5926     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5927     * vCC (r1).  Useful for integer division and modulus.
5928     *
5929     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5930     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5931     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5932     *      rem-double/2addr
5933     */
5934    /* binop/2addr vA, vB */
5935    mov     r9, rINST, lsr #8           @ r9<- A+
5936    mov     r1, rINST, lsr #12          @ r1<- B
5937    and     r9, r9, #15
5938    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5939    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5940    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5941    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5942    .if 1
5943    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5944    beq     common_errDivideByZero
5945    .endif
5946    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5947
5948                               @ optional op; may set condition codes
5949    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5951    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5952    GOTO_OPCODE(ip)                     @ jump to next instruction
5953    /* 12-15 instructions */
5954
5955
5956
5957/* ------------------------------ */
5958    .balign 64
5959.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5960/* File: armv5te/OP_AND_LONG_2ADDR.S */
5961/* File: armv5te/binopWide2addr.S */
5962    /*
5963     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5964     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5965     * This could be an ARM instruction or a function call.  (If the result
5966     * comes back in a register other than r0, you can override "result".)
5967     *
5968     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5969     * vCC (r1).  Useful for integer division and modulus.
5970     *
5971     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5972     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5973     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5974     *      rem-double/2addr
5975     */
5976    /* binop/2addr vA, vB */
5977    mov     r9, rINST, lsr #8           @ r9<- A+
5978    mov     r1, rINST, lsr #12          @ r1<- B
5979    and     r9, r9, #15
5980    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5981    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5982    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5983    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5984    .if 0
5985    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5986    beq     common_errDivideByZero
5987    .endif
5988    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5989
5990    and     r0, r0, r2                           @ optional op; may set condition codes
5991    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5993    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5994    GOTO_OPCODE(ip)                     @ jump to next instruction
5995    /* 12-15 instructions */
5996
5997
5998
5999/* ------------------------------ */
6000    .balign 64
6001.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6002/* File: armv5te/OP_OR_LONG_2ADDR.S */
6003/* File: armv5te/binopWide2addr.S */
6004    /*
6005     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6006     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6007     * This could be an ARM instruction or a function call.  (If the result
6008     * comes back in a register other than r0, you can override "result".)
6009     *
6010     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6011     * vCC (r1).  Useful for integer division and modulus.
6012     *
6013     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6014     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6015     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6016     *      rem-double/2addr
6017     */
6018    /* binop/2addr vA, vB */
6019    mov     r9, rINST, lsr #8           @ r9<- A+
6020    mov     r1, rINST, lsr #12          @ r1<- B
6021    and     r9, r9, #15
6022    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6023    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6024    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6025    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6026    .if 0
6027    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6028    beq     common_errDivideByZero
6029    .endif
6030    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6031
6032    orr     r0, r0, r2                           @ optional op; may set condition codes
6033    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6034    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6035    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6036    GOTO_OPCODE(ip)                     @ jump to next instruction
6037    /* 12-15 instructions */
6038
6039
6040
6041/* ------------------------------ */
6042    .balign 64
6043.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6044/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6045/* File: armv5te/binopWide2addr.S */
6046    /*
6047     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6048     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6049     * This could be an ARM instruction or a function call.  (If the result
6050     * comes back in a register other than r0, you can override "result".)
6051     *
6052     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6053     * vCC (r1).  Useful for integer division and modulus.
6054     *
6055     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6056     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6057     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6058     *      rem-double/2addr
6059     */
6060    /* binop/2addr vA, vB */
6061    mov     r9, rINST, lsr #8           @ r9<- A+
6062    mov     r1, rINST, lsr #12          @ r1<- B
6063    and     r9, r9, #15
6064    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6065    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6066    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6067    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6068    .if 0
6069    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6070    beq     common_errDivideByZero
6071    .endif
6072    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6073
6074    eor     r0, r0, r2                           @ optional op; may set condition codes
6075    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6076    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6077    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6078    GOTO_OPCODE(ip)                     @ jump to next instruction
6079    /* 12-15 instructions */
6080
6081
6082
6083/* ------------------------------ */
6084    .balign 64
6085.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6086/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6087    /*
6088     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6089     * 32-bit shift distance.
6090     */
6091    /* shl-long/2addr vA, vB */
6092    mov     r9, rINST, lsr #8           @ r9<- A+
6093    mov     r3, rINST, lsr #12          @ r3<- B
6094    and     r9, r9, #15
6095    GET_VREG(r2, r3)                    @ r2<- vB
6096    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6097    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6098    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6099
6100    mov     r1, r1, asl r2              @  r1<- r1 << r2
6101    rsb     r3, r2, #32                 @  r3<- 32 - r2
6102    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6103    subs    ip, r2, #32                 @  ip<- r2 - 32
6104    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6105    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6106    mov     r0, r0, asl r2              @  r0<- r0 << r2
6107    b       .LOP_SHL_LONG_2ADDR_finish
6108
6109/* ------------------------------ */
6110    .balign 64
6111.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6112/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6113    /*
6114     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6115     * 32-bit shift distance.
6116     */
6117    /* shr-long/2addr vA, vB */
6118    mov     r9, rINST, lsr #8           @ r9<- A+
6119    mov     r3, rINST, lsr #12          @ r3<- B
6120    and     r9, r9, #15
6121    GET_VREG(r2, r3)                    @ r2<- vB
6122    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6123    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6124    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6125
6126    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6127    rsb     r3, r2, #32                 @  r3<- 32 - r2
6128    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6129    subs    ip, r2, #32                 @  ip<- r2 - 32
6130    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6131    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6132    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6133    b       .LOP_SHR_LONG_2ADDR_finish
6134
6135/* ------------------------------ */
6136    .balign 64
6137.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6138/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6139    /*
6140     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6141     * 32-bit shift distance.
6142     */
6143    /* ushr-long/2addr vA, vB */
6144    mov     r9, rINST, lsr #8           @ r9<- A+
6145    mov     r3, rINST, lsr #12          @ r3<- B
6146    and     r9, r9, #15
6147    GET_VREG(r2, r3)                    @ r2<- vB
6148    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6149    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6150    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6151
6152    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6153    rsb     r3, r2, #32                 @  r3<- 32 - r2
6154    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6155    subs    ip, r2, #32                 @  ip<- r2 - 32
6156    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6157    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6158    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6159    b       .LOP_USHR_LONG_2ADDR_finish
6160
6161/* ------------------------------ */
6162    .balign 64
6163.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6164/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6165/* File: arm-vfp/fbinop2addr.S */
6166    /*
6167     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6168     * an "instr" line that specifies an instruction that performs
6169     * "s2 = s0 op s1".
6170     *
6171     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6172     */
6173    /* binop/2addr vA, vB */
6174    mov     r3, rINST, lsr #12          @ r3<- B
6175    mov     r9, rINST, lsr #8           @ r9<- A+
6176    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6177    and     r9, r9, #15                 @ r9<- A
6178    flds    s1, [r3]                    @ s1<- vB
6179    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6180    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6181    flds    s0, [r9]                    @ s0<- vA
6182
6183    fadds   s2, s0, s1                              @ s2<- op
6184    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6185    fsts    s2, [r9]                    @ vAA<- s2
6186    GOTO_OPCODE(ip)                     @ jump to next instruction
6187
6188
6189/* ------------------------------ */
6190    .balign 64
6191.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6192/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6193/* File: arm-vfp/fbinop2addr.S */
6194    /*
6195     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6196     * an "instr" line that specifies an instruction that performs
6197     * "s2 = s0 op s1".
6198     *
6199     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6200     */
6201    /* binop/2addr vA, vB */
6202    mov     r3, rINST, lsr #12          @ r3<- B
6203    mov     r9, rINST, lsr #8           @ r9<- A+
6204    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6205    and     r9, r9, #15                 @ r9<- A
6206    flds    s1, [r3]                    @ s1<- vB
6207    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6208    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6209    flds    s0, [r9]                    @ s0<- vA
6210
6211    fsubs   s2, s0, s1                              @ s2<- op
6212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6213    fsts    s2, [r9]                    @ vAA<- s2
6214    GOTO_OPCODE(ip)                     @ jump to next instruction
6215
6216
6217/* ------------------------------ */
6218    .balign 64
6219.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6220/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6221/* File: arm-vfp/fbinop2addr.S */
6222    /*
6223     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6224     * an "instr" line that specifies an instruction that performs
6225     * "s2 = s0 op s1".
6226     *
6227     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6228     */
6229    /* binop/2addr vA, vB */
6230    mov     r3, rINST, lsr #12          @ r3<- B
6231    mov     r9, rINST, lsr #8           @ r9<- A+
6232    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6233    and     r9, r9, #15                 @ r9<- A
6234    flds    s1, [r3]                    @ s1<- vB
6235    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6236    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6237    flds    s0, [r9]                    @ s0<- vA
6238
6239    fmuls   s2, s0, s1                              @ s2<- op
6240    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6241    fsts    s2, [r9]                    @ vAA<- s2
6242    GOTO_OPCODE(ip)                     @ jump to next instruction
6243
6244
6245/* ------------------------------ */
6246    .balign 64
6247.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6248/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6249/* File: arm-vfp/fbinop2addr.S */
6250    /*
6251     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6252     * an "instr" line that specifies an instruction that performs
6253     * "s2 = s0 op s1".
6254     *
6255     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6256     */
6257    /* binop/2addr vA, vB */
6258    mov     r3, rINST, lsr #12          @ r3<- B
6259    mov     r9, rINST, lsr #8           @ r9<- A+
6260    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6261    and     r9, r9, #15                 @ r9<- A
6262    flds    s1, [r3]                    @ s1<- vB
6263    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6264    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265    flds    s0, [r9]                    @ s0<- vA
6266
6267    fdivs   s2, s0, s1                              @ s2<- op
6268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269    fsts    s2, [r9]                    @ vAA<- s2
6270    GOTO_OPCODE(ip)                     @ jump to next instruction
6271
6272
6273/* ------------------------------ */
6274    .balign 64
6275.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6276/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6277/* EABI doesn't define a float remainder function, but libm does */
6278/* File: armv5te/binop2addr.S */
6279    /*
6280     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6281     * that specifies an instruction that performs "result = r0 op r1".
6282     * This could be an ARM instruction or a function call.  (If the result
6283     * comes back in a register other than r0, you can override "result".)
6284     *
6285     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6286     * vCC (r1).  Useful for integer division and modulus.
6287     *
6288     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6289     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6290     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6291     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6292     */
6293    /* binop/2addr vA, vB */
6294    mov     r9, rINST, lsr #8           @ r9<- A+
6295    mov     r3, rINST, lsr #12          @ r3<- B
6296    and     r9, r9, #15
6297    GET_VREG(r1, r3)                    @ r1<- vB
6298    GET_VREG(r0, r9)                    @ r0<- vA
6299    .if 0
6300    cmp     r1, #0                      @ is second operand zero?
6301    beq     common_errDivideByZero
6302    .endif
6303    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6304
6305                               @ optional op; may set condition codes
6306    bl      fmodf                              @ r0<- op, r0-r3 changed
6307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6308    SET_VREG(r0, r9)               @ vAA<- r0
6309    GOTO_OPCODE(ip)                     @ jump to next instruction
6310    /* 10-13 instructions */
6311
6312
6313
6314/* ------------------------------ */
6315    .balign 64
6316.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6317/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6318/* File: arm-vfp/fbinopWide2addr.S */
6319    /*
6320     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6321     * an "instr" line that specifies an instruction that performs
6322     * "d2 = d0 op d1".
6323     *
6324     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6325     *      div-double/2addr
6326     */
6327    /* binop/2addr vA, vB */
6328    mov     r3, rINST, lsr #12          @ r3<- B
6329    mov     r9, rINST, lsr #8           @ r9<- A+
6330    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6331    and     r9, r9, #15                 @ r9<- A
6332    fldd    d1, [r3]                    @ d1<- vB
6333    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6334    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6335    fldd    d0, [r9]                    @ d0<- vA
6336
6337    faddd   d2, d0, d1                              @ d2<- op
6338    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6339    fstd    d2, [r9]                    @ vAA<- d2
6340    GOTO_OPCODE(ip)                     @ jump to next instruction
6341
6342
6343/* ------------------------------ */
6344    .balign 64
6345.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6346/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6347/* File: arm-vfp/fbinopWide2addr.S */
6348    /*
6349     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6350     * an "instr" line that specifies an instruction that performs
6351     * "d2 = d0 op d1".
6352     *
6353     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6354     *      div-double/2addr
6355     */
6356    /* binop/2addr vA, vB */
6357    mov     r3, rINST, lsr #12          @ r3<- B
6358    mov     r9, rINST, lsr #8           @ r9<- A+
6359    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6360    and     r9, r9, #15                 @ r9<- A
6361    fldd    d1, [r3]                    @ d1<- vB
6362    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6363    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6364    fldd    d0, [r9]                    @ d0<- vA
6365
6366    fsubd   d2, d0, d1                              @ d2<- op
6367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6368    fstd    d2, [r9]                    @ vAA<- d2
6369    GOTO_OPCODE(ip)                     @ jump to next instruction
6370
6371
6372/* ------------------------------ */
6373    .balign 64
6374.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6375/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6376/* File: arm-vfp/fbinopWide2addr.S */
6377    /*
6378     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6379     * an "instr" line that specifies an instruction that performs
6380     * "d2 = d0 op d1".
6381     *
6382     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6383     *      div-double/2addr
6384     */
6385    /* binop/2addr vA, vB */
6386    mov     r3, rINST, lsr #12          @ r3<- B
6387    mov     r9, rINST, lsr #8           @ r9<- A+
6388    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6389    and     r9, r9, #15                 @ r9<- A
6390    fldd    d1, [r3]                    @ d1<- vB
6391    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6392    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6393    fldd    d0, [r9]                    @ d0<- vA
6394
6395    fmuld   d2, d0, d1                              @ d2<- op
6396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6397    fstd    d2, [r9]                    @ vAA<- d2
6398    GOTO_OPCODE(ip)                     @ jump to next instruction
6399
6400
6401/* ------------------------------ */
6402    .balign 64
6403.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6404/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6405/* File: arm-vfp/fbinopWide2addr.S */
6406    /*
6407     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6408     * an "instr" line that specifies an instruction that performs
6409     * "d2 = d0 op d1".
6410     *
6411     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6412     *      div-double/2addr
6413     */
6414    /* binop/2addr vA, vB */
6415    mov     r3, rINST, lsr #12          @ r3<- B
6416    mov     r9, rINST, lsr #8           @ r9<- A+
6417    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6418    and     r9, r9, #15                 @ r9<- A
6419    fldd    d1, [r3]                    @ d1<- vB
6420    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6421    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6422    fldd    d0, [r9]                    @ d0<- vA
6423
6424    fdivd   d2, d0, d1                              @ d2<- op
6425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6426    fstd    d2, [r9]                    @ vAA<- d2
6427    GOTO_OPCODE(ip)                     @ jump to next instruction
6428
6429
6430/* ------------------------------ */
6431    .balign 64
6432.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6433/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6434/* EABI doesn't define a double remainder function, but libm does */
6435/* File: armv5te/binopWide2addr.S */
6436    /*
6437     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6438     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6439     * This could be an ARM instruction or a function call.  (If the result
6440     * comes back in a register other than r0, you can override "result".)
6441     *
6442     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6443     * vCC (r1).  Useful for integer division and modulus.
6444     *
6445     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6446     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6447     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6448     *      rem-double/2addr
6449     */
6450    /* binop/2addr vA, vB */
6451    mov     r9, rINST, lsr #8           @ r9<- A+
6452    mov     r1, rINST, lsr #12          @ r1<- B
6453    and     r9, r9, #15
6454    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6455    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6456    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6457    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6458    .if 0
6459    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6460    beq     common_errDivideByZero
6461    .endif
6462    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6463
6464                               @ optional op; may set condition codes
6465    bl      fmod                              @ result<- op, r0-r3 changed
6466    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6467    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6468    GOTO_OPCODE(ip)                     @ jump to next instruction
6469    /* 12-15 instructions */
6470
6471
6472
6473/* ------------------------------ */
6474    .balign 64
6475.L_OP_ADD_INT_LIT16: /* 0xd0 */
6476/* File: armv5te/OP_ADD_INT_LIT16.S */
6477/* File: armv5te/binopLit16.S */
6478    /*
6479     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6480     * that specifies an instruction that performs "result = r0 op r1".
6481     * This could be an ARM instruction or a function call.  (If the result
6482     * comes back in a register other than r0, you can override "result".)
6483     *
6484     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6485     * vCC (r1).  Useful for integer division and modulus.
6486     *
6487     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6488     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6489     */
6490    /* binop/lit16 vA, vB, #+CCCC */
6491    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6492    mov     r2, rINST, lsr #12          @ r2<- B
6493    mov     r9, rINST, lsr #8           @ r9<- A+
6494    GET_VREG(r0, r2)                    @ r0<- vB
6495    and     r9, r9, #15
6496    .if 0
6497    cmp     r1, #0                      @ is second operand zero?
6498    beq     common_errDivideByZero
6499    .endif
6500    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6501
6502    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6504    SET_VREG(r0, r9)               @ vAA<- r0
6505    GOTO_OPCODE(ip)                     @ jump to next instruction
6506    /* 10-13 instructions */
6507
6508
6509
6510/* ------------------------------ */
6511    .balign 64
6512.L_OP_RSUB_INT: /* 0xd1 */
6513/* File: armv5te/OP_RSUB_INT.S */
6514/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6515/* File: armv5te/binopLit16.S */
6516    /*
6517     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6518     * that specifies an instruction that performs "result = r0 op r1".
6519     * This could be an ARM instruction or a function call.  (If the result
6520     * comes back in a register other than r0, you can override "result".)
6521     *
6522     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6523     * vCC (r1).  Useful for integer division and modulus.
6524     *
6525     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6526     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6527     */
6528    /* binop/lit16 vA, vB, #+CCCC */
6529    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6530    mov     r2, rINST, lsr #12          @ r2<- B
6531    mov     r9, rINST, lsr #8           @ r9<- A+
6532    GET_VREG(r0, r2)                    @ r0<- vB
6533    and     r9, r9, #15
6534    .if 0
6535    cmp     r1, #0                      @ is second operand zero?
6536    beq     common_errDivideByZero
6537    .endif
6538    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6539
6540    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6541    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6542    SET_VREG(r0, r9)               @ vAA<- r0
6543    GOTO_OPCODE(ip)                     @ jump to next instruction
6544    /* 10-13 instructions */
6545
6546
6547
6548/* ------------------------------ */
6549    .balign 64
6550.L_OP_MUL_INT_LIT16: /* 0xd2 */
6551/* File: armv5te/OP_MUL_INT_LIT16.S */
6552/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6553/* File: armv5te/binopLit16.S */
6554    /*
6555     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6556     * that specifies an instruction that performs "result = r0 op r1".
6557     * This could be an ARM instruction or a function call.  (If the result
6558     * comes back in a register other than r0, you can override "result".)
6559     *
6560     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6561     * vCC (r1).  Useful for integer division and modulus.
6562     *
6563     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6564     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6565     */
6566    /* binop/lit16 vA, vB, #+CCCC */
6567    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6568    mov     r2, rINST, lsr #12          @ r2<- B
6569    mov     r9, rINST, lsr #8           @ r9<- A+
6570    GET_VREG(r0, r2)                    @ r0<- vB
6571    and     r9, r9, #15
6572    .if 0
6573    cmp     r1, #0                      @ is second operand zero?
6574    beq     common_errDivideByZero
6575    .endif
6576    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6577
6578    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6580    SET_VREG(r0, r9)               @ vAA<- r0
6581    GOTO_OPCODE(ip)                     @ jump to next instruction
6582    /* 10-13 instructions */
6583
6584
6585
6586/* ------------------------------ */
6587    .balign 64
6588.L_OP_DIV_INT_LIT16: /* 0xd3 */
6589/* File: armv5te/OP_DIV_INT_LIT16.S */
6590/* File: armv5te/binopLit16.S */
6591    /*
6592     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6593     * that specifies an instruction that performs "result = r0 op r1".
6594     * This could be an ARM instruction or a function call.  (If the result
6595     * comes back in a register other than r0, you can override "result".)
6596     *
6597     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6598     * vCC (r1).  Useful for integer division and modulus.
6599     *
6600     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6601     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6602     */
6603    /* binop/lit16 vA, vB, #+CCCC */
6604    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6605    mov     r2, rINST, lsr #12          @ r2<- B
6606    mov     r9, rINST, lsr #8           @ r9<- A+
6607    GET_VREG(r0, r2)                    @ r0<- vB
6608    and     r9, r9, #15
6609    .if 1
6610    cmp     r1, #0                      @ is second operand zero?
6611    beq     common_errDivideByZero
6612    .endif
6613    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6614
6615    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6617    SET_VREG(r0, r9)               @ vAA<- r0
6618    GOTO_OPCODE(ip)                     @ jump to next instruction
6619    /* 10-13 instructions */
6620
6621
6622
6623/* ------------------------------ */
6624    .balign 64
6625.L_OP_REM_INT_LIT16: /* 0xd4 */
6626/* File: armv5te/OP_REM_INT_LIT16.S */
6627/* idivmod returns quotient in r0 and remainder in r1 */
6628/* File: armv5te/binopLit16.S */
6629    /*
6630     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6631     * that specifies an instruction that performs "result = r0 op r1".
6632     * This could be an ARM instruction or a function call.  (If the result
6633     * comes back in a register other than r0, you can override "result".)
6634     *
6635     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6636     * vCC (r1).  Useful for integer division and modulus.
6637     *
6638     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6639     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6640     */
6641    /* binop/lit16 vA, vB, #+CCCC */
6642    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6643    mov     r2, rINST, lsr #12          @ r2<- B
6644    mov     r9, rINST, lsr #8           @ r9<- A+
6645    GET_VREG(r0, r2)                    @ r0<- vB
6646    and     r9, r9, #15
6647    .if 1
6648    cmp     r1, #0                      @ is second operand zero?
6649    beq     common_errDivideByZero
6650    .endif
6651    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6652
6653    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6655    SET_VREG(r1, r9)               @ vAA<- r1
6656    GOTO_OPCODE(ip)                     @ jump to next instruction
6657    /* 10-13 instructions */
6658
6659
6660
6661/* ------------------------------ */
6662    .balign 64
6663.L_OP_AND_INT_LIT16: /* 0xd5 */
6664/* File: armv5te/OP_AND_INT_LIT16.S */
6665/* File: armv5te/binopLit16.S */
6666    /*
6667     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6668     * that specifies an instruction that performs "result = r0 op r1".
6669     * This could be an ARM instruction or a function call.  (If the result
6670     * comes back in a register other than r0, you can override "result".)
6671     *
6672     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6673     * vCC (r1).  Useful for integer division and modulus.
6674     *
6675     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6676     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6677     */
6678    /* binop/lit16 vA, vB, #+CCCC */
6679    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6680    mov     r2, rINST, lsr #12          @ r2<- B
6681    mov     r9, rINST, lsr #8           @ r9<- A+
6682    GET_VREG(r0, r2)                    @ r0<- vB
6683    and     r9, r9, #15
6684    .if 0
6685    cmp     r1, #0                      @ is second operand zero?
6686    beq     common_errDivideByZero
6687    .endif
6688    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6689
6690    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6691    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6692    SET_VREG(r0, r9)               @ vAA<- r0
6693    GOTO_OPCODE(ip)                     @ jump to next instruction
6694    /* 10-13 instructions */
6695
6696
6697
6698/* ------------------------------ */
6699    .balign 64
6700.L_OP_OR_INT_LIT16: /* 0xd6 */
6701/* File: armv5te/OP_OR_INT_LIT16.S */
6702/* File: armv5te/binopLit16.S */
6703    /*
6704     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6705     * that specifies an instruction that performs "result = r0 op r1".
6706     * This could be an ARM instruction or a function call.  (If the result
6707     * comes back in a register other than r0, you can override "result".)
6708     *
6709     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6710     * vCC (r1).  Useful for integer division and modulus.
6711     *
6712     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6713     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6714     */
6715    /* binop/lit16 vA, vB, #+CCCC */
6716    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6717    mov     r2, rINST, lsr #12          @ r2<- B
6718    mov     r9, rINST, lsr #8           @ r9<- A+
6719    GET_VREG(r0, r2)                    @ r0<- vB
6720    and     r9, r9, #15
6721    .if 0
6722    cmp     r1, #0                      @ is second operand zero?
6723    beq     common_errDivideByZero
6724    .endif
6725    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6726
6727    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6729    SET_VREG(r0, r9)               @ vAA<- r0
6730    GOTO_OPCODE(ip)                     @ jump to next instruction
6731    /* 10-13 instructions */
6732
6733
6734
6735/* ------------------------------ */
6736    .balign 64
6737.L_OP_XOR_INT_LIT16: /* 0xd7 */
6738/* File: armv5te/OP_XOR_INT_LIT16.S */
6739/* File: armv5te/binopLit16.S */
6740    /*
6741     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6742     * that specifies an instruction that performs "result = r0 op r1".
6743     * This could be an ARM instruction or a function call.  (If the result
6744     * comes back in a register other than r0, you can override "result".)
6745     *
6746     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6747     * vCC (r1).  Useful for integer division and modulus.
6748     *
6749     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6750     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6751     */
6752    /* binop/lit16 vA, vB, #+CCCC */
6753    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6754    mov     r2, rINST, lsr #12          @ r2<- B
6755    mov     r9, rINST, lsr #8           @ r9<- A+
6756    GET_VREG(r0, r2)                    @ r0<- vB
6757    and     r9, r9, #15
6758    .if 0
6759    cmp     r1, #0                      @ is second operand zero?
6760    beq     common_errDivideByZero
6761    .endif
6762    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6763
6764    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6765    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6766    SET_VREG(r0, r9)               @ vAA<- r0
6767    GOTO_OPCODE(ip)                     @ jump to next instruction
6768    /* 10-13 instructions */
6769
6770
6771
6772/* ------------------------------ */
6773    .balign 64
6774.L_OP_ADD_INT_LIT8: /* 0xd8 */
6775/* File: armv5te/OP_ADD_INT_LIT8.S */
6776/* File: armv5te/binopLit8.S */
6777    /*
6778     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6779     * that specifies an instruction that performs "result = r0 op r1".
6780     * This could be an ARM instruction or a function call.  (If the result
6781     * comes back in a register other than r0, you can override "result".)
6782     *
6783     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6784     * vCC (r1).  Useful for integer division and modulus.
6785     *
6786     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6787     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6788     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6789     */
6790    /* binop/lit8 vAA, vBB, #+CC */
6791    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6792    mov     r9, rINST, lsr #8           @ r9<- AA
6793    and     r2, r3, #255                @ r2<- BB
6794    GET_VREG(r0, r2)                    @ r0<- vBB
6795    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6796    .if 0
6797    @cmp     r1, #0                      @ is second operand zero?
6798    beq     common_errDivideByZero
6799    .endif
6800    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6801
6802                               @ optional op; may set condition codes
6803    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6804    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6805    SET_VREG(r0, r9)               @ vAA<- r0
6806    GOTO_OPCODE(ip)                     @ jump to next instruction
6807    /* 10-12 instructions */
6808
6809
6810
6811/* ------------------------------ */
6812    .balign 64
6813.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6814/* File: armv5te/OP_RSUB_INT_LIT8.S */
6815/* File: armv5te/binopLit8.S */
6816    /*
6817     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6818     * that specifies an instruction that performs "result = r0 op r1".
6819     * This could be an ARM instruction or a function call.  (If the result
6820     * comes back in a register other than r0, you can override "result".)
6821     *
6822     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6823     * vCC (r1).  Useful for integer division and modulus.
6824     *
6825     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6826     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6827     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6828     */
6829    /* binop/lit8 vAA, vBB, #+CC */
6830    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6831    mov     r9, rINST, lsr #8           @ r9<- AA
6832    and     r2, r3, #255                @ r2<- BB
6833    GET_VREG(r0, r2)                    @ r0<- vBB
6834    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6835    .if 0
6836    @cmp     r1, #0                      @ is second operand zero?
6837    beq     common_errDivideByZero
6838    .endif
6839    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6840
6841                               @ optional op; may set condition codes
6842    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6844    SET_VREG(r0, r9)               @ vAA<- r0
6845    GOTO_OPCODE(ip)                     @ jump to next instruction
6846    /* 10-12 instructions */
6847
6848
6849
6850/* ------------------------------ */
6851    .balign 64
6852.L_OP_MUL_INT_LIT8: /* 0xda */
6853/* File: armv5te/OP_MUL_INT_LIT8.S */
6854/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6855/* File: armv5te/binopLit8.S */
6856    /*
6857     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6858     * that specifies an instruction that performs "result = r0 op r1".
6859     * This could be an ARM instruction or a function call.  (If the result
6860     * comes back in a register other than r0, you can override "result".)
6861     *
6862     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6863     * vCC (r1).  Useful for integer division and modulus.
6864     *
6865     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6866     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6867     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6868     */
6869    /* binop/lit8 vAA, vBB, #+CC */
6870    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6871    mov     r9, rINST, lsr #8           @ r9<- AA
6872    and     r2, r3, #255                @ r2<- BB
6873    GET_VREG(r0, r2)                    @ r0<- vBB
6874    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6875    .if 0
6876    @cmp     r1, #0                      @ is second operand zero?
6877    beq     common_errDivideByZero
6878    .endif
6879    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6880
6881                               @ optional op; may set condition codes
6882    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6883    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6884    SET_VREG(r0, r9)               @ vAA<- r0
6885    GOTO_OPCODE(ip)                     @ jump to next instruction
6886    /* 10-12 instructions */
6887
6888
6889
6890/* ------------------------------ */
6891    .balign 64
6892.L_OP_DIV_INT_LIT8: /* 0xdb */
6893/* File: armv5te/OP_DIV_INT_LIT8.S */
6894/* File: armv5te/binopLit8.S */
6895    /*
6896     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6897     * that specifies an instruction that performs "result = r0 op r1".
6898     * This could be an ARM instruction or a function call.  (If the result
6899     * comes back in a register other than r0, you can override "result".)
6900     *
6901     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6902     * vCC (r1).  Useful for integer division and modulus.
6903     *
6904     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6905     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6906     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6907     */
6908    /* binop/lit8 vAA, vBB, #+CC */
6909    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6910    mov     r9, rINST, lsr #8           @ r9<- AA
6911    and     r2, r3, #255                @ r2<- BB
6912    GET_VREG(r0, r2)                    @ r0<- vBB
6913    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6914    .if 1
6915    @cmp     r1, #0                      @ is second operand zero?
6916    beq     common_errDivideByZero
6917    .endif
6918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6919
6920                               @ optional op; may set condition codes
6921    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6923    SET_VREG(r0, r9)               @ vAA<- r0
6924    GOTO_OPCODE(ip)                     @ jump to next instruction
6925    /* 10-12 instructions */
6926
6927
6928
6929/* ------------------------------ */
6930    .balign 64
6931.L_OP_REM_INT_LIT8: /* 0xdc */
6932/* File: armv5te/OP_REM_INT_LIT8.S */
6933/* idivmod returns quotient in r0 and remainder in r1 */
6934/* File: armv5te/binopLit8.S */
6935    /*
6936     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6937     * that specifies an instruction that performs "result = r0 op r1".
6938     * This could be an ARM instruction or a function call.  (If the result
6939     * comes back in a register other than r0, you can override "result".)
6940     *
6941     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6942     * vCC (r1).  Useful for integer division and modulus.
6943     *
6944     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6945     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6946     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6947     */
6948    /* binop/lit8 vAA, vBB, #+CC */
6949    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6950    mov     r9, rINST, lsr #8           @ r9<- AA
6951    and     r2, r3, #255                @ r2<- BB
6952    GET_VREG(r0, r2)                    @ r0<- vBB
6953    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6954    .if 1
6955    @cmp     r1, #0                      @ is second operand zero?
6956    beq     common_errDivideByZero
6957    .endif
6958    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6959
6960                               @ optional op; may set condition codes
6961    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6962    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6963    SET_VREG(r1, r9)               @ vAA<- r1
6964    GOTO_OPCODE(ip)                     @ jump to next instruction
6965    /* 10-12 instructions */
6966
6967
6968
6969/* ------------------------------ */
6970    .balign 64
6971.L_OP_AND_INT_LIT8: /* 0xdd */
6972/* File: armv5te/OP_AND_INT_LIT8.S */
6973/* File: armv5te/binopLit8.S */
6974    /*
6975     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6976     * that specifies an instruction that performs "result = r0 op r1".
6977     * This could be an ARM instruction or a function call.  (If the result
6978     * comes back in a register other than r0, you can override "result".)
6979     *
6980     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6981     * vCC (r1).  Useful for integer division and modulus.
6982     *
6983     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6984     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6985     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6986     */
6987    /* binop/lit8 vAA, vBB, #+CC */
6988    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6989    mov     r9, rINST, lsr #8           @ r9<- AA
6990    and     r2, r3, #255                @ r2<- BB
6991    GET_VREG(r0, r2)                    @ r0<- vBB
6992    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6993    .if 0
6994    @cmp     r1, #0                      @ is second operand zero?
6995    beq     common_errDivideByZero
6996    .endif
6997    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6998
6999                               @ optional op; may set condition codes
7000    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7001    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7002    SET_VREG(r0, r9)               @ vAA<- r0
7003    GOTO_OPCODE(ip)                     @ jump to next instruction
7004    /* 10-12 instructions */
7005
7006
7007
7008/* ------------------------------ */
7009    .balign 64
7010.L_OP_OR_INT_LIT8: /* 0xde */
7011/* File: armv5te/OP_OR_INT_LIT8.S */
7012/* File: armv5te/binopLit8.S */
7013    /*
7014     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7015     * that specifies an instruction that performs "result = r0 op r1".
7016     * This could be an ARM instruction or a function call.  (If the result
7017     * comes back in a register other than r0, you can override "result".)
7018     *
7019     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7020     * vCC (r1).  Useful for integer division and modulus.
7021     *
7022     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7023     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7024     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7025     */
7026    /* binop/lit8 vAA, vBB, #+CC */
7027    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7028    mov     r9, rINST, lsr #8           @ r9<- AA
7029    and     r2, r3, #255                @ r2<- BB
7030    GET_VREG(r0, r2)                    @ r0<- vBB
7031    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7032    .if 0
7033    @cmp     r1, #0                      @ is second operand zero?
7034    beq     common_errDivideByZero
7035    .endif
7036    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7037
7038                               @ optional op; may set condition codes
7039    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7040    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7041    SET_VREG(r0, r9)               @ vAA<- r0
7042    GOTO_OPCODE(ip)                     @ jump to next instruction
7043    /* 10-12 instructions */
7044
7045
7046
7047/* ------------------------------ */
7048    .balign 64
7049.L_OP_XOR_INT_LIT8: /* 0xdf */
7050/* File: armv5te/OP_XOR_INT_LIT8.S */
7051/* File: armv5te/binopLit8.S */
7052    /*
7053     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7054     * that specifies an instruction that performs "result = r0 op r1".
7055     * This could be an ARM instruction or a function call.  (If the result
7056     * comes back in a register other than r0, you can override "result".)
7057     *
7058     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7059     * vCC (r1).  Useful for integer division and modulus.
7060     *
7061     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7062     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7063     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7064     */
7065    /* binop/lit8 vAA, vBB, #+CC */
7066    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7067    mov     r9, rINST, lsr #8           @ r9<- AA
7068    and     r2, r3, #255                @ r2<- BB
7069    GET_VREG(r0, r2)                    @ r0<- vBB
7070    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7071    .if 0
7072    @cmp     r1, #0                      @ is second operand zero?
7073    beq     common_errDivideByZero
7074    .endif
7075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7076
7077                               @ optional op; may set condition codes
7078    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7079    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7080    SET_VREG(r0, r9)               @ vAA<- r0
7081    GOTO_OPCODE(ip)                     @ jump to next instruction
7082    /* 10-12 instructions */
7083
7084
7085
7086/* ------------------------------ */
7087    .balign 64
7088.L_OP_SHL_INT_LIT8: /* 0xe0 */
7089/* File: armv5te/OP_SHL_INT_LIT8.S */
7090/* File: armv5te/binopLit8.S */
7091    /*
7092     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7093     * that specifies an instruction that performs "result = r0 op r1".
7094     * This could be an ARM instruction or a function call.  (If the result
7095     * comes back in a register other than r0, you can override "result".)
7096     *
7097     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7098     * vCC (r1).  Useful for integer division and modulus.
7099     *
7100     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7101     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7102     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7103     */
7104    /* binop/lit8 vAA, vBB, #+CC */
7105    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7106    mov     r9, rINST, lsr #8           @ r9<- AA
7107    and     r2, r3, #255                @ r2<- BB
7108    GET_VREG(r0, r2)                    @ r0<- vBB
7109    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7110    .if 0
7111    @cmp     r1, #0                      @ is second operand zero?
7112    beq     common_errDivideByZero
7113    .endif
7114    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7115
7116    and     r1, r1, #31                           @ optional op; may set condition codes
7117    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7119    SET_VREG(r0, r9)               @ vAA<- r0
7120    GOTO_OPCODE(ip)                     @ jump to next instruction
7121    /* 10-12 instructions */
7122
7123
7124
7125/* ------------------------------ */
7126    .balign 64
7127.L_OP_SHR_INT_LIT8: /* 0xe1 */
7128/* File: armv5te/OP_SHR_INT_LIT8.S */
7129/* File: armv5te/binopLit8.S */
7130    /*
7131     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7132     * that specifies an instruction that performs "result = r0 op r1".
7133     * This could be an ARM instruction or a function call.  (If the result
7134     * comes back in a register other than r0, you can override "result".)
7135     *
7136     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7137     * vCC (r1).  Useful for integer division and modulus.
7138     *
7139     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7140     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7141     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7142     */
7143    /* binop/lit8 vAA, vBB, #+CC */
7144    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7145    mov     r9, rINST, lsr #8           @ r9<- AA
7146    and     r2, r3, #255                @ r2<- BB
7147    GET_VREG(r0, r2)                    @ r0<- vBB
7148    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7149    .if 0
7150    @cmp     r1, #0                      @ is second operand zero?
7151    beq     common_errDivideByZero
7152    .endif
7153    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7154
7155    and     r1, r1, #31                           @ optional op; may set condition codes
7156    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7158    SET_VREG(r0, r9)               @ vAA<- r0
7159    GOTO_OPCODE(ip)                     @ jump to next instruction
7160    /* 10-12 instructions */
7161
7162
7163
7164/* ------------------------------ */
7165    .balign 64
7166.L_OP_USHR_INT_LIT8: /* 0xe2 */
7167/* File: armv5te/OP_USHR_INT_LIT8.S */
7168/* File: armv5te/binopLit8.S */
7169    /*
7170     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7171     * that specifies an instruction that performs "result = r0 op r1".
7172     * This could be an ARM instruction or a function call.  (If the result
7173     * comes back in a register other than r0, you can override "result".)
7174     *
7175     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7176     * vCC (r1).  Useful for integer division and modulus.
7177     *
7178     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7179     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7180     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7181     */
7182    /* binop/lit8 vAA, vBB, #+CC */
7183    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7184    mov     r9, rINST, lsr #8           @ r9<- AA
7185    and     r2, r3, #255                @ r2<- BB
7186    GET_VREG(r0, r2)                    @ r0<- vBB
7187    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7188    .if 0
7189    @cmp     r1, #0                      @ is second operand zero?
7190    beq     common_errDivideByZero
7191    .endif
7192    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7193
7194    and     r1, r1, #31                           @ optional op; may set condition codes
7195    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7196    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7197    SET_VREG(r0, r9)               @ vAA<- r0
7198    GOTO_OPCODE(ip)                     @ jump to next instruction
7199    /* 10-12 instructions */
7200
7201
7202
7203/* ------------------------------ */
7204    .balign 64
7205.L_OP_UNUSED_E3: /* 0xe3 */
7206/* File: armv5te/OP_UNUSED_E3.S */
7207/* File: armv5te/unused.S */
7208    bl      common_abort
7209
7210
7211
7212/* ------------------------------ */
7213    .balign 64
7214.L_OP_UNUSED_E4: /* 0xe4 */
7215/* File: armv5te/OP_UNUSED_E4.S */
7216/* File: armv5te/unused.S */
7217    bl      common_abort
7218
7219
7220
7221/* ------------------------------ */
7222    .balign 64
7223.L_OP_UNUSED_E5: /* 0xe5 */
7224/* File: armv5te/OP_UNUSED_E5.S */
7225/* File: armv5te/unused.S */
7226    bl      common_abort
7227
7228
7229
7230/* ------------------------------ */
7231    .balign 64
7232.L_OP_UNUSED_E6: /* 0xe6 */
7233/* File: armv5te/OP_UNUSED_E6.S */
7234/* File: armv5te/unused.S */
7235    bl      common_abort
7236
7237
7238
7239/* ------------------------------ */
7240    .balign 64
7241.L_OP_UNUSED_E7: /* 0xe7 */
7242/* File: armv5te/OP_UNUSED_E7.S */
7243/* File: armv5te/unused.S */
7244    bl      common_abort
7245
7246
7247
7248/* ------------------------------ */
7249    .balign 64
7250.L_OP_UNUSED_E8: /* 0xe8 */
7251/* File: armv5te/OP_UNUSED_E8.S */
7252/* File: armv5te/unused.S */
7253    bl      common_abort
7254
7255
7256
7257/* ------------------------------ */
7258    .balign 64
7259.L_OP_UNUSED_E9: /* 0xe9 */
7260/* File: armv5te/OP_UNUSED_E9.S */
7261/* File: armv5te/unused.S */
7262    bl      common_abort
7263
7264
7265
7266/* ------------------------------ */
7267    .balign 64
7268.L_OP_UNUSED_EA: /* 0xea */
7269/* File: armv5te/OP_UNUSED_EA.S */
7270/* File: armv5te/unused.S */
7271    bl      common_abort
7272
7273
7274
7275/* ------------------------------ */
7276    .balign 64
7277.L_OP_UNUSED_EB: /* 0xeb */
7278/* File: armv5te/OP_UNUSED_EB.S */
7279/* File: armv5te/unused.S */
7280    bl      common_abort
7281
7282
7283
7284/* ------------------------------ */
7285    .balign 64
7286.L_OP_BREAKPOINT: /* 0xec */
7287/* File: armv5te/OP_BREAKPOINT.S */
7288/* File: armv5te/unused.S */
7289    bl      common_abort
7290
7291
7292
7293/* ------------------------------ */
7294    .balign 64
7295.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7296/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7297    /*
7298     * Handle a throw-verification-error instruction.  This throws an
7299     * exception for an error discovered during verification.  The
7300     * exception is indicated by AA, with some detail provided by BBBB.
7301     */
7302    /* op AA, ref@BBBB */
7303    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7304    FETCH(r2, 1)                        @ r2<- BBBB
7305    EXPORT_PC()                         @ export the PC
7306    mov     r1, rINST, lsr #8           @ r1<- AA
7307    bl      dvmThrowVerificationError   @ always throws
7308    b       common_exceptionThrown      @ handle exception
7309
7310
7311/* ------------------------------ */
7312    .balign 64
7313.L_OP_EXECUTE_INLINE: /* 0xee */
7314/* File: armv5te/OP_EXECUTE_INLINE.S */
7315    /*
7316     * Execute a "native inline" instruction.
7317     *
7318     * We need to call an InlineOp4Func:
7319     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7320     *
7321     * The first four args are in r0-r3, pointer to return value storage
7322     * is on the stack.  The function's return value is a flag that tells
7323     * us if an exception was thrown.
7324     */
7325    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7326    FETCH(r10, 1)                       @ r10<- BBBB
7327    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7328    EXPORT_PC()                         @ can throw
7329    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7330    mov     r0, rINST, lsr #12          @ r0<- B
7331    str     r1, [sp]                    @ push &glue->retval
7332    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7333    add     sp, sp, #8                  @ pop stack
7334    cmp     r0, #0                      @ test boolean result of inline
7335    beq     common_exceptionThrown      @ returned false, handle exception
7336    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7337    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7338    GOTO_OPCODE(ip)                     @ jump to next instruction
7339
7340/* ------------------------------ */
7341    .balign 64
7342.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7343/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7344    /*
7345     * Execute a "native inline" instruction, using "/range" semantics.
7346     * Same idea as execute-inline, but we get the args differently.
7347     *
7348     * We need to call an InlineOp4Func:
7349     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7350     *
7351     * The first four args are in r0-r3, pointer to return value storage
7352     * is on the stack.  The function's return value is a flag that tells
7353     * us if an exception was thrown.
7354     */
7355    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7356    FETCH(r10, 1)                       @ r10<- BBBB
7357    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7358    EXPORT_PC()                         @ can throw
7359    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7360    mov     r0, rINST, lsr #8           @ r0<- AA
7361    str     r1, [sp]                    @ push &glue->retval
7362    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7363    add     sp, sp, #8                  @ pop stack
7364    cmp     r0, #0                      @ test boolean result of inline
7365    beq     common_exceptionThrown      @ returned false, handle exception
7366    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7368    GOTO_OPCODE(ip)                     @ jump to next instruction
7369
7370/* ------------------------------ */
7371    .balign 64
7372.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7373/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7374    /*
7375     * invoke-direct-empty is a no-op in a "standard" interpreter.
7376     */
7377    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7378    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7379    GOTO_OPCODE(ip)                     @ execute it
7380
7381/* ------------------------------ */
7382    .balign 64
7383.L_OP_UNUSED_F1: /* 0xf1 */
7384/* File: armv5te/OP_UNUSED_F1.S */
7385/* File: armv5te/unused.S */
7386    bl      common_abort
7387
7388
7389
7390/* ------------------------------ */
7391    .balign 64
7392.L_OP_IGET_QUICK: /* 0xf2 */
7393/* File: armv5te/OP_IGET_QUICK.S */
7394    /* For: iget-quick, iget-object-quick */
7395    /* op vA, vB, offset@CCCC */
7396    mov     r2, rINST, lsr #12          @ r2<- B
7397    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7398    FETCH(r1, 1)                        @ r1<- field byte offset
7399    cmp     r3, #0                      @ check object for null
7400    mov     r2, rINST, lsr #8           @ r2<- A(+)
7401    beq     common_errNullObject        @ object was null
7402    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7403    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7404    and     r2, r2, #15
7405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7406    SET_VREG(r0, r2)                    @ fp[A]<- r0
7407    GOTO_OPCODE(ip)                     @ jump to next instruction
7408
7409
7410/* ------------------------------ */
7411    .balign 64
7412.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7413/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7414    /* iget-wide-quick vA, vB, offset@CCCC */
7415    mov     r2, rINST, lsr #12          @ r2<- B
7416    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7417    FETCH(r1, 1)                        @ r1<- field byte offset
7418    cmp     r3, #0                      @ check object for null
7419    mov     r2, rINST, lsr #8           @ r2<- A(+)
7420    beq     common_errNullObject        @ object was null
7421    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7422    and     r2, r2, #15
7423    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7424    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7426    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7427    GOTO_OPCODE(ip)                     @ jump to next instruction
7428
7429
7430/* ------------------------------ */
7431    .balign 64
7432.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7433/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7434/* File: armv5te/OP_IGET_QUICK.S */
7435    /* For: iget-quick, iget-object-quick */
7436    /* op vA, vB, offset@CCCC */
7437    mov     r2, rINST, lsr #12          @ r2<- B
7438    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7439    FETCH(r1, 1)                        @ r1<- field byte offset
7440    cmp     r3, #0                      @ check object for null
7441    mov     r2, rINST, lsr #8           @ r2<- A(+)
7442    beq     common_errNullObject        @ object was null
7443    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7444    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7445    and     r2, r2, #15
7446    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7447    SET_VREG(r0, r2)                    @ fp[A]<- r0
7448    GOTO_OPCODE(ip)                     @ jump to next instruction
7449
7450
7451
7452/* ------------------------------ */
7453    .balign 64
7454.L_OP_IPUT_QUICK: /* 0xf5 */
7455/* File: armv5te/OP_IPUT_QUICK.S */
7456    /* For: iput-quick, iput-object-quick */
7457    /* op vA, vB, offset@CCCC */
7458    mov     r2, rINST, lsr #12          @ r2<- B
7459    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7460    FETCH(r1, 1)                        @ r1<- field byte offset
7461    cmp     r3, #0                      @ check object for null
7462    mov     r2, rINST, lsr #8           @ r2<- A(+)
7463    beq     common_errNullObject        @ object was null
7464    and     r2, r2, #15
7465    GET_VREG(r0, r2)                    @ r0<- fp[A]
7466    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7467    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7469    GOTO_OPCODE(ip)                     @ jump to next instruction
7470
7471
7472/* ------------------------------ */
7473    .balign 64
7474.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7475/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7476    /* iput-wide-quick vA, vB, offset@CCCC */
7477    mov     r0, rINST, lsr #8           @ r0<- A(+)
7478    mov     r1, rINST, lsr #12          @ r1<- B
7479    and     r0, r0, #15
7480    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7481    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7482    cmp     r2, #0                      @ check object for null
7483    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7484    beq     common_errNullObject        @ object was null
7485    FETCH(r3, 1)                        @ r3<- field byte offset
7486    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7487    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7488    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7489    GOTO_OPCODE(ip)                     @ jump to next instruction
7490
7491
7492/* ------------------------------ */
7493    .balign 64
7494.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7495/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7496/* File: armv5te/OP_IPUT_QUICK.S */
7497    /* For: iput-quick, iput-object-quick */
7498    /* op vA, vB, offset@CCCC */
7499    mov     r2, rINST, lsr #12          @ r2<- B
7500    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7501    FETCH(r1, 1)                        @ r1<- field byte offset
7502    cmp     r3, #0                      @ check object for null
7503    mov     r2, rINST, lsr #8           @ r2<- A(+)
7504    beq     common_errNullObject        @ object was null
7505    and     r2, r2, #15
7506    GET_VREG(r0, r2)                    @ r0<- fp[A]
7507    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7508    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7509    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7510    GOTO_OPCODE(ip)                     @ jump to next instruction
7511
7512
7513
7514/* ------------------------------ */
7515    .balign 64
7516.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7517/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7518    /*
7519     * Handle an optimized virtual method call.
7520     *
7521     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7522     */
7523    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7524    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7525    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7526    FETCH(r1, 1)                        @ r1<- BBBB
7527    .if     (!0)
7528    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7529    .endif
7530    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7531    cmp     r2, #0                      @ is "this" null?
7532    beq     common_errNullObject        @ null "this", throw exception
7533    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7534    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7535    EXPORT_PC()                         @ invoke must export
7536    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7537    bl      common_invokeMethodNoRange @ continue on
7538
7539/* ------------------------------ */
7540    .balign 64
7541.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7542/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7543/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7544    /*
7545     * Handle an optimized virtual method call.
7546     *
7547     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7548     */
7549    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7550    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7551    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7552    FETCH(r1, 1)                        @ r1<- BBBB
7553    .if     (!1)
7554    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7555    .endif
7556    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7557    cmp     r2, #0                      @ is "this" null?
7558    beq     common_errNullObject        @ null "this", throw exception
7559    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7560    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7561    EXPORT_PC()                         @ invoke must export
7562    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7563    bl      common_invokeMethodRange @ continue on
7564
7565
7566/* ------------------------------ */
7567    .balign 64
7568.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7569/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7570    /*
7571     * Handle an optimized "super" method call.
7572     *
7573     * for: [opt] invoke-super-quick, invoke-super-quick/range
7574     */
7575    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7576    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7577    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7578    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7579    .if     (!0)
7580    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7581    .endif
7582    FETCH(r1, 1)                        @ r1<- BBBB
7583    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7584    EXPORT_PC()                         @ must export for invoke
7585    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7586    GET_VREG(r3, r10)                   @ r3<- "this"
7587    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7588    cmp     r3, #0                      @ null "this" ref?
7589    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7590    beq     common_errNullObject        @ "this" is null, throw exception
7591    bl      common_invokeMethodNoRange @ continue on
7592
7593
7594/* ------------------------------ */
7595    .balign 64
7596.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7597/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7598/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7599    /*
7600     * Handle an optimized "super" method call.
7601     *
7602     * for: [opt] invoke-super-quick, invoke-super-quick/range
7603     */
7604    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7605    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7606    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7607    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7608    .if     (!1)
7609    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7610    .endif
7611    FETCH(r1, 1)                        @ r1<- BBBB
7612    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7613    EXPORT_PC()                         @ must export for invoke
7614    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7615    GET_VREG(r3, r10)                   @ r3<- "this"
7616    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7617    cmp     r3, #0                      @ null "this" ref?
7618    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7619    beq     common_errNullObject        @ "this" is null, throw exception
7620    bl      common_invokeMethodRange @ continue on
7621
7622
7623
7624/* ------------------------------ */
7625    .balign 64
7626.L_OP_UNUSED_FC: /* 0xfc */
7627/* File: armv5te/OP_UNUSED_FC.S */
7628/* File: armv5te/unused.S */
7629    bl      common_abort
7630
7631
7632
7633/* ------------------------------ */
7634    .balign 64
7635.L_OP_UNUSED_FD: /* 0xfd */
7636/* File: armv5te/OP_UNUSED_FD.S */
7637/* File: armv5te/unused.S */
7638    bl      common_abort
7639
7640
7641
7642/* ------------------------------ */
7643    .balign 64
7644.L_OP_UNUSED_FE: /* 0xfe */
7645/* File: armv5te/OP_UNUSED_FE.S */
7646/* File: armv5te/unused.S */
7647    bl      common_abort
7648
7649
7650
7651/* ------------------------------ */
7652    .balign 64
7653.L_OP_UNUSED_FF: /* 0xff */
7654/* File: armv5te/OP_UNUSED_FF.S */
7655/* File: armv5te/unused.S */
7656    bl      common_abort
7657
7658
7659
7660
7661    .balign 64
7662    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7663    .global dvmAsmInstructionEnd
7664dvmAsmInstructionEnd:
7665
7666/*
7667 * ===========================================================================
7668 *  Sister implementations
7669 * ===========================================================================
7670 */
7671    .global dvmAsmSisterStart
7672    .type   dvmAsmSisterStart, %function
7673    .text
7674    .balign 4
7675dvmAsmSisterStart:
7676
7677/* continuation for OP_CONST_STRING */
7678
7679    /*
7680     * Continuation if the String has not yet been resolved.
7681     *  r1: BBBB (String ref)
7682     *  r9: target register
7683     */
7684.LOP_CONST_STRING_resolve:
7685    EXPORT_PC()
7686    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7687    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7688    bl      dvmResolveString            @ r0<- String reference
7689    cmp     r0, #0                      @ failed?
7690    beq     common_exceptionThrown      @ yup, handle the exception
7691    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7692    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7693    SET_VREG(r0, r9)                    @ vAA<- r0
7694    GOTO_OPCODE(ip)                     @ jump to next instruction
7695
7696
7697/* continuation for OP_CONST_STRING_JUMBO */
7698
7699    /*
7700     * Continuation if the String has not yet been resolved.
7701     *  r1: BBBBBBBB (String ref)
7702     *  r9: target register
7703     */
7704.LOP_CONST_STRING_JUMBO_resolve:
7705    EXPORT_PC()
7706    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7707    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7708    bl      dvmResolveString            @ r0<- String reference
7709    cmp     r0, #0                      @ failed?
7710    beq     common_exceptionThrown      @ yup, handle the exception
7711    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7712    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7713    SET_VREG(r0, r9)                    @ vAA<- r0
7714    GOTO_OPCODE(ip)                     @ jump to next instruction
7715
7716
7717/* continuation for OP_CONST_CLASS */
7718
7719    /*
7720     * Continuation if the Class has not yet been resolved.
7721     *  r1: BBBB (Class ref)
7722     *  r9: target register
7723     */
7724.LOP_CONST_CLASS_resolve:
7725    EXPORT_PC()
7726    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7727    mov     r2, #1                      @ r2<- true
7728    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7729    bl      dvmResolveClass             @ r0<- Class reference
7730    cmp     r0, #0                      @ failed?
7731    beq     common_exceptionThrown      @ yup, handle the exception
7732    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7733    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7734    SET_VREG(r0, r9)                    @ vAA<- r0
7735    GOTO_OPCODE(ip)                     @ jump to next instruction
7736
7737
7738/* continuation for OP_CHECK_CAST */
7739
7740    /*
7741     * Trivial test failed, need to perform full check.  This is common.
7742     *  r0 holds obj->clazz
7743     *  r1 holds class resolved from BBBB
7744     *  r9 holds object
7745     */
7746.LOP_CHECK_CAST_fullcheck:
7747    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7748    cmp     r0, #0                      @ failed?
7749    bne     .LOP_CHECK_CAST_okay            @ no, success
7750
7751    @ A cast has failed.  We need to throw a ClassCastException with the
7752    @ class of the object that failed to be cast.
7753    EXPORT_PC()                         @ about to throw
7754    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7755    ldr     r0, .LstrClassCastExceptionPtr
7756    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7757    bl      dvmThrowExceptionWithClassMessage
7758    b       common_exceptionThrown
7759
7760    /*
7761     * Resolution required.  This is the least-likely path.
7762     *
7763     *  r2 holds BBBB
7764     *  r9 holds object
7765     */
7766.LOP_CHECK_CAST_resolve:
7767    EXPORT_PC()                         @ resolve() could throw
7768    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7769    mov     r1, r2                      @ r1<- BBBB
7770    mov     r2, #0                      @ r2<- false
7771    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7772    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7773    cmp     r0, #0                      @ got null?
7774    beq     common_exceptionThrown      @ yes, handle exception
7775    mov     r1, r0                      @ r1<- class resolved from BBB
7776    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7777    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7778
7779.LstrClassCastExceptionPtr:
7780    .word   .LstrClassCastException
7781
7782
7783/* continuation for OP_INSTANCE_OF */
7784
7785    /*
7786     * Trivial test failed, need to perform full check.  This is common.
7787     *  r0 holds obj->clazz
7788     *  r1 holds class resolved from BBBB
7789     *  r9 holds A
7790     */
7791.LOP_INSTANCE_OF_fullcheck:
7792    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7793    @ fall through to OP_INSTANCE_OF_store
7794
7795    /*
7796     * r0 holds boolean result
7797     * r9 holds A
7798     */
7799.LOP_INSTANCE_OF_store:
7800    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7801    SET_VREG(r0, r9)                    @ vA<- r0
7802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7803    GOTO_OPCODE(ip)                     @ jump to next instruction
7804
7805    /*
7806     * Trivial test succeeded, save and bail.
7807     *  r9 holds A
7808     */
7809.LOP_INSTANCE_OF_trivial:
7810    mov     r0, #1                      @ indicate success
7811    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7813    SET_VREG(r0, r9)                    @ vA<- r0
7814    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7815    GOTO_OPCODE(ip)                     @ jump to next instruction
7816
7817    /*
7818     * Resolution required.  This is the least-likely path.
7819     *
7820     *  r3 holds BBBB
7821     *  r9 holds A
7822     */
7823.LOP_INSTANCE_OF_resolve:
7824    EXPORT_PC()                         @ resolve() could throw
7825    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7826    mov     r1, r3                      @ r1<- BBBB
7827    mov     r2, #1                      @ r2<- true
7828    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7829    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7830    cmp     r0, #0                      @ got null?
7831    beq     common_exceptionThrown      @ yes, handle exception
7832    mov     r1, r0                      @ r1<- class resolved from BBB
7833    mov     r3, rINST, lsr #12          @ r3<- B
7834    GET_VREG(r0, r3)                    @ r0<- vB (object)
7835    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7836    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7837
7838
7839/* continuation for OP_NEW_INSTANCE */
7840
7841    .balign 32                          @ minimize cache lines
7842.LOP_NEW_INSTANCE_finish: @ r0=new object
7843    mov     r3, rINST, lsr #8           @ r3<- AA
7844    cmp     r0, #0                      @ failed?
7845    beq     common_exceptionThrown      @ yes, handle the exception
7846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7848    SET_VREG(r0, r3)                    @ vAA<- r0
7849    GOTO_OPCODE(ip)                     @ jump to next instruction
7850
7851    /*
7852     * Class initialization required.
7853     *
7854     *  r0 holds class object
7855     */
7856.LOP_NEW_INSTANCE_needinit:
7857    mov     r9, r0                      @ save r0
7858    bl      dvmInitClass                @ initialize class
7859    cmp     r0, #0                      @ check boolean result
7860    mov     r0, r9                      @ restore r0
7861    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7862    b       common_exceptionThrown      @ failed, deal with init exception
7863
7864    /*
7865     * Resolution required.  This is the least-likely path.
7866     *
7867     *  r1 holds BBBB
7868     */
7869.LOP_NEW_INSTANCE_resolve:
7870    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7871    mov     r2, #0                      @ r2<- false
7872    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7873    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7874    cmp     r0, #0                      @ got null?
7875    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7876    b       common_exceptionThrown      @ yes, handle exception
7877
7878.LstrInstantiationErrorPtr:
7879    .word   .LstrInstantiationError
7880
7881
7882/* continuation for OP_NEW_ARRAY */
7883
7884
7885    /*
7886     * Resolve class.  (This is an uncommon case.)
7887     *
7888     *  r1 holds array length
7889     *  r2 holds class ref CCCC
7890     */
7891.LOP_NEW_ARRAY_resolve:
7892    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7893    mov     r9, r1                      @ r9<- length (save)
7894    mov     r1, r2                      @ r1<- CCCC
7895    mov     r2, #0                      @ r2<- false
7896    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7897    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7898    cmp     r0, #0                      @ got null?
7899    mov     r1, r9                      @ r1<- length (restore)
7900    beq     common_exceptionThrown      @ yes, handle exception
7901    @ fall through to OP_NEW_ARRAY_finish
7902
7903    /*
7904     * Finish allocation.
7905     *
7906     *  r0 holds class
7907     *  r1 holds array length
7908     */
7909.LOP_NEW_ARRAY_finish:
7910    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7911    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7912    cmp     r0, #0                      @ failed?
7913    mov     r2, rINST, lsr #8           @ r2<- A+
7914    beq     common_exceptionThrown      @ yes, handle the exception
7915    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7916    and     r2, r2, #15                 @ r2<- A
7917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7918    SET_VREG(r0, r2)                    @ vA<- r0
7919    GOTO_OPCODE(ip)                     @ jump to next instruction
7920
7921
7922/* continuation for OP_FILLED_NEW_ARRAY */
7923
7924    /*
7925     * On entry:
7926     *  r0 holds array class
7927     *  r10 holds AA or BA
7928     */
7929.LOP_FILLED_NEW_ARRAY_continue:
7930    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7931    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7932    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7933    .if     0
7934    mov     r1, r10                     @ r1<- AA (length)
7935    .else
7936    mov     r1, r10, lsr #4             @ r1<- B (length)
7937    .endif
7938    cmp     r3, #'I'                    @ array of ints?
7939    cmpne   r3, #'L'                    @ array of objects?
7940    cmpne   r3, #'['                    @ array of arrays?
7941    mov     r9, r1                      @ save length in r9
7942    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7943    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7944    cmp     r0, #0                      @ null return?
7945    beq     common_exceptionThrown      @ alloc failed, handle exception
7946
7947    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7948    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7949    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7950    subs    r9, r9, #1                  @ length--, check for neg
7951    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7952    bmi     2f                          @ was zero, bail
7953
7954    @ copy values from registers into the array
7955    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7956    .if     0
7957    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79581:  ldr     r3, [r2], #4                @ r3<- *r2++
7959    subs    r9, r9, #1                  @ count--
7960    str     r3, [r0], #4                @ *contents++ = vX
7961    bpl     1b
7962    @ continue at 2
7963    .else
7964    cmp     r9, #4                      @ length was initially 5?
7965    and     r2, r10, #15                @ r2<- A
7966    bne     1f                          @ <= 4 args, branch
7967    GET_VREG(r3, r2)                    @ r3<- vA
7968    sub     r9, r9, #1                  @ count--
7969    str     r3, [r0, #16]               @ contents[4] = vA
79701:  and     r2, r1, #15                 @ r2<- F/E/D/C
7971    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7972    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7973    subs    r9, r9, #1                  @ count--
7974    str     r3, [r0], #4                @ *contents++ = vX
7975    bpl     1b
7976    @ continue at 2
7977    .endif
7978
79792:
7980    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7981    GOTO_OPCODE(ip)                     @ execute it
7982
7983    /*
7984     * Throw an exception indicating that we have not implemented this
7985     * mode of filled-new-array.
7986     */
7987.LOP_FILLED_NEW_ARRAY_notimpl:
7988    ldr     r0, .L_strInternalError
7989    ldr     r1, .L_strFilledNewArrayNotImpl
7990    bl      dvmThrowException
7991    b       common_exceptionThrown
7992
7993    .if     (!0)                 @ define in one or the other, not both
7994.L_strFilledNewArrayNotImpl:
7995    .word   .LstrFilledNewArrayNotImpl
7996.L_strInternalError:
7997    .word   .LstrInternalError
7998    .endif
7999
8000
8001/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8002
8003    /*
8004     * On entry:
8005     *  r0 holds array class
8006     *  r10 holds AA or BA
8007     */
8008.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8009    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8010    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8011    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8012    .if     1
8013    mov     r1, r10                     @ r1<- AA (length)
8014    .else
8015    mov     r1, r10, lsr #4             @ r1<- B (length)
8016    .endif
8017    cmp     r3, #'I'                    @ array of ints?
8018    cmpne   r3, #'L'                    @ array of objects?
8019    cmpne   r3, #'['                    @ array of arrays?
8020    mov     r9, r1                      @ save length in r9
8021    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8022    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8023    cmp     r0, #0                      @ null return?
8024    beq     common_exceptionThrown      @ alloc failed, handle exception
8025
8026    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8027    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8028    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8029    subs    r9, r9, #1                  @ length--, check for neg
8030    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8031    bmi     2f                          @ was zero, bail
8032
8033    @ copy values from registers into the array
8034    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8035    .if     1
8036    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80371:  ldr     r3, [r2], #4                @ r3<- *r2++
8038    subs    r9, r9, #1                  @ count--
8039    str     r3, [r0], #4                @ *contents++ = vX
8040    bpl     1b
8041    @ continue at 2
8042    .else
8043    cmp     r9, #4                      @ length was initially 5?
8044    and     r2, r10, #15                @ r2<- A
8045    bne     1f                          @ <= 4 args, branch
8046    GET_VREG(r3, r2)                    @ r3<- vA
8047    sub     r9, r9, #1                  @ count--
8048    str     r3, [r0, #16]               @ contents[4] = vA
80491:  and     r2, r1, #15                 @ r2<- F/E/D/C
8050    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8051    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8052    subs    r9, r9, #1                  @ count--
8053    str     r3, [r0], #4                @ *contents++ = vX
8054    bpl     1b
8055    @ continue at 2
8056    .endif
8057
80582:
8059    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8060    GOTO_OPCODE(ip)                     @ execute it
8061
8062    /*
8063     * Throw an exception indicating that we have not implemented this
8064     * mode of filled-new-array.
8065     */
8066.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8067    ldr     r0, .L_strInternalError
8068    ldr     r1, .L_strFilledNewArrayNotImpl
8069    bl      dvmThrowException
8070    b       common_exceptionThrown
8071
8072    .if     (!1)                 @ define in one or the other, not both
8073.L_strFilledNewArrayNotImpl:
8074    .word   .LstrFilledNewArrayNotImpl
8075.L_strInternalError:
8076    .word   .LstrInternalError
8077    .endif
8078
8079
8080/* continuation for OP_CMPL_FLOAT */
8081.LOP_CMPL_FLOAT_finish:
8082    SET_VREG(r0, r9)                    @ vAA<- r0
8083    GOTO_OPCODE(ip)                     @ jump to next instruction
8084
8085
8086/* continuation for OP_CMPG_FLOAT */
8087.LOP_CMPG_FLOAT_finish:
8088    SET_VREG(r0, r9)                    @ vAA<- r0
8089    GOTO_OPCODE(ip)                     @ jump to next instruction
8090
8091
8092/* continuation for OP_CMPL_DOUBLE */
8093.LOP_CMPL_DOUBLE_finish:
8094    SET_VREG(r0, r9)                    @ vAA<- r0
8095    GOTO_OPCODE(ip)                     @ jump to next instruction
8096
8097
8098/* continuation for OP_CMPG_DOUBLE */
8099.LOP_CMPG_DOUBLE_finish:
8100    SET_VREG(r0, r9)                    @ vAA<- r0
8101    GOTO_OPCODE(ip)                     @ jump to next instruction
8102
8103
8104/* continuation for OP_CMP_LONG */
8105
8106.LOP_CMP_LONG_less:
8107    mvn     r1, #0                      @ r1<- -1
8108    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8109    @ instead, we just replicate the tail end.
8110    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8111    SET_VREG(r1, r9)                    @ vAA<- r1
8112    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8113    GOTO_OPCODE(ip)                     @ jump to next instruction
8114
8115.LOP_CMP_LONG_greater:
8116    mov     r1, #1                      @ r1<- 1
8117    @ fall through to _finish
8118
8119.LOP_CMP_LONG_finish:
8120    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8121    SET_VREG(r1, r9)                    @ vAA<- r1
8122    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8123    GOTO_OPCODE(ip)                     @ jump to next instruction
8124
8125
8126/* continuation for OP_AGET_WIDE */
8127
8128.LOP_AGET_WIDE_finish:
8129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8130    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8131    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8132    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8133    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8134    GOTO_OPCODE(ip)                     @ jump to next instruction
8135
8136
8137/* continuation for OP_APUT_WIDE */
8138
8139.LOP_APUT_WIDE_finish:
8140    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8141    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8143    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8144    GOTO_OPCODE(ip)                     @ jump to next instruction
8145
8146
8147/* continuation for OP_APUT_OBJECT */
8148    /*
8149     * On entry:
8150     *  r1 = vBB (arrayObj)
8151     *  r9 = vAA (obj)
8152     *  r10 = offset into array (vBB + vCC * width)
8153     */
8154.LOP_APUT_OBJECT_finish:
8155    cmp     r9, #0                      @ storing null reference?
8156    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8157    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8158    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8159    bl      dvmCanPutArrayElement       @ test object type vs. array type
8160    cmp     r0, #0                      @ okay?
8161    beq     common_errArrayStore        @ no
8162.LOP_APUT_OBJECT_skip_check:
8163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8164    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8165    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8166    GOTO_OPCODE(ip)                     @ jump to next instruction
8167
8168
8169/* continuation for OP_IGET */
8170
8171    /*
8172     * Currently:
8173     *  r0 holds resolved field
8174     *  r9 holds object
8175     */
8176.LOP_IGET_finish:
8177    @bl      common_squeak0
8178    cmp     r9, #0                      @ check object for null
8179    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8180    beq     common_errNullObject        @ object was null
8181    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8182    mov     r2, rINST, lsr #8           @ r2<- A+
8183    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8184    and     r2, r2, #15                 @ r2<- A
8185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8186    SET_VREG(r0, r2)                    @ fp[A]<- r0
8187    GOTO_OPCODE(ip)                     @ jump to next instruction
8188
8189
8190/* continuation for OP_IGET_WIDE */
8191
8192    /*
8193     * Currently:
8194     *  r0 holds resolved field
8195     *  r9 holds object
8196     */
8197.LOP_IGET_WIDE_finish:
8198    cmp     r9, #0                      @ check object for null
8199    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8200    beq     common_errNullObject        @ object was null
8201    mov     r2, rINST, lsr #8           @ r2<- A+
8202    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8203    and     r2, r2, #15                 @ r2<- A
8204    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8205    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8207    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8208    GOTO_OPCODE(ip)                     @ jump to next instruction
8209
8210
8211/* continuation for OP_IGET_OBJECT */
8212
8213    /*
8214     * Currently:
8215     *  r0 holds resolved field
8216     *  r9 holds object
8217     */
8218.LOP_IGET_OBJECT_finish:
8219    @bl      common_squeak0
8220    cmp     r9, #0                      @ check object for null
8221    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8222    beq     common_errNullObject        @ object was null
8223    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8224    mov     r2, rINST, lsr #8           @ r2<- A+
8225    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8226    and     r2, r2, #15                 @ r2<- A
8227    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8228    SET_VREG(r0, r2)                    @ fp[A]<- r0
8229    GOTO_OPCODE(ip)                     @ jump to next instruction
8230
8231
8232/* continuation for OP_IGET_BOOLEAN */
8233
8234    /*
8235     * Currently:
8236     *  r0 holds resolved field
8237     *  r9 holds object
8238     */
8239.LOP_IGET_BOOLEAN_finish:
8240    @bl      common_squeak1
8241    cmp     r9, #0                      @ check object for null
8242    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8243    beq     common_errNullObject        @ object was null
8244    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8245    mov     r2, rINST, lsr #8           @ r2<- A+
8246    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8247    and     r2, r2, #15                 @ r2<- A
8248    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8249    SET_VREG(r0, r2)                    @ fp[A]<- r0
8250    GOTO_OPCODE(ip)                     @ jump to next instruction
8251
8252
8253/* continuation for OP_IGET_BYTE */
8254
8255    /*
8256     * Currently:
8257     *  r0 holds resolved field
8258     *  r9 holds object
8259     */
8260.LOP_IGET_BYTE_finish:
8261    @bl      common_squeak2
8262    cmp     r9, #0                      @ check object for null
8263    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8264    beq     common_errNullObject        @ object was null
8265    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8266    mov     r2, rINST, lsr #8           @ r2<- A+
8267    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8268    and     r2, r2, #15                 @ r2<- A
8269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8270    SET_VREG(r0, r2)                    @ fp[A]<- r0
8271    GOTO_OPCODE(ip)                     @ jump to next instruction
8272
8273
8274/* continuation for OP_IGET_CHAR */
8275
8276    /*
8277     * Currently:
8278     *  r0 holds resolved field
8279     *  r9 holds object
8280     */
8281.LOP_IGET_CHAR_finish:
8282    @bl      common_squeak3
8283    cmp     r9, #0                      @ check object for null
8284    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8285    beq     common_errNullObject        @ object was null
8286    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8287    mov     r2, rINST, lsr #8           @ r2<- A+
8288    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8289    and     r2, r2, #15                 @ r2<- A
8290    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8291    SET_VREG(r0, r2)                    @ fp[A]<- r0
8292    GOTO_OPCODE(ip)                     @ jump to next instruction
8293
8294
8295/* continuation for OP_IGET_SHORT */
8296
8297    /*
8298     * Currently:
8299     *  r0 holds resolved field
8300     *  r9 holds object
8301     */
8302.LOP_IGET_SHORT_finish:
8303    @bl      common_squeak4
8304    cmp     r9, #0                      @ check object for null
8305    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8306    beq     common_errNullObject        @ object was null
8307    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8308    mov     r2, rINST, lsr #8           @ r2<- A+
8309    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8310    and     r2, r2, #15                 @ r2<- A
8311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8312    SET_VREG(r0, r2)                    @ fp[A]<- r0
8313    GOTO_OPCODE(ip)                     @ jump to next instruction
8314
8315
8316/* continuation for OP_IPUT */
8317
8318    /*
8319     * Currently:
8320     *  r0 holds resolved field
8321     *  r9 holds object
8322     */
8323.LOP_IPUT_finish:
8324    @bl      common_squeak0
8325    mov     r1, rINST, lsr #8           @ r1<- A+
8326    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8327    and     r1, r1, #15                 @ r1<- A
8328    cmp     r9, #0                      @ check object for null
8329    GET_VREG(r0, r1)                    @ r0<- fp[A]
8330    beq     common_errNullObject        @ object was null
8331    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8332    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8333    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8334    GOTO_OPCODE(ip)                     @ jump to next instruction
8335
8336
8337/* continuation for OP_IPUT_WIDE */
8338
8339    /*
8340     * Currently:
8341     *  r0 holds resolved field
8342     *  r9 holds object
8343     */
8344.LOP_IPUT_WIDE_finish:
8345    mov     r2, rINST, lsr #8           @ r2<- A+
8346    cmp     r9, #0                      @ check object for null
8347    and     r2, r2, #15                 @ r2<- A
8348    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8349    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8350    beq     common_errNullObject        @ object was null
8351    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8352    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8353    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8354    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8355    GOTO_OPCODE(ip)                     @ jump to next instruction
8356
8357
8358/* continuation for OP_IPUT_OBJECT */
8359
8360    /*
8361     * Currently:
8362     *  r0 holds resolved field
8363     *  r9 holds object
8364     */
8365.LOP_IPUT_OBJECT_finish:
8366    @bl      common_squeak0
8367    mov     r1, rINST, lsr #8           @ r1<- A+
8368    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8369    and     r1, r1, #15                 @ r1<- A
8370    cmp     r9, #0                      @ check object for null
8371    GET_VREG(r0, r1)                    @ r0<- fp[A]
8372    beq     common_errNullObject        @ object was null
8373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8375    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8376    GOTO_OPCODE(ip)                     @ jump to next instruction
8377
8378
8379/* continuation for OP_IPUT_BOOLEAN */
8380
8381    /*
8382     * Currently:
8383     *  r0 holds resolved field
8384     *  r9 holds object
8385     */
8386.LOP_IPUT_BOOLEAN_finish:
8387    @bl      common_squeak1
8388    mov     r1, rINST, lsr #8           @ r1<- A+
8389    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8390    and     r1, r1, #15                 @ r1<- A
8391    cmp     r9, #0                      @ check object for null
8392    GET_VREG(r0, r1)                    @ r0<- fp[A]
8393    beq     common_errNullObject        @ object was null
8394    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8395    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8396    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8397    GOTO_OPCODE(ip)                     @ jump to next instruction
8398
8399
8400/* continuation for OP_IPUT_BYTE */
8401
8402    /*
8403     * Currently:
8404     *  r0 holds resolved field
8405     *  r9 holds object
8406     */
8407.LOP_IPUT_BYTE_finish:
8408    @bl      common_squeak2
8409    mov     r1, rINST, lsr #8           @ r1<- A+
8410    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8411    and     r1, r1, #15                 @ r1<- A
8412    cmp     r9, #0                      @ check object for null
8413    GET_VREG(r0, r1)                    @ r0<- fp[A]
8414    beq     common_errNullObject        @ object was null
8415    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8416    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8417    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8418    GOTO_OPCODE(ip)                     @ jump to next instruction
8419
8420
8421/* continuation for OP_IPUT_CHAR */
8422
8423    /*
8424     * Currently:
8425     *  r0 holds resolved field
8426     *  r9 holds object
8427     */
8428.LOP_IPUT_CHAR_finish:
8429    @bl      common_squeak3
8430    mov     r1, rINST, lsr #8           @ r1<- A+
8431    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8432    and     r1, r1, #15                 @ r1<- A
8433    cmp     r9, #0                      @ check object for null
8434    GET_VREG(r0, r1)                    @ r0<- fp[A]
8435    beq     common_errNullObject        @ object was null
8436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8438    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8439    GOTO_OPCODE(ip)                     @ jump to next instruction
8440
8441
8442/* continuation for OP_IPUT_SHORT */
8443
8444    /*
8445     * Currently:
8446     *  r0 holds resolved field
8447     *  r9 holds object
8448     */
8449.LOP_IPUT_SHORT_finish:
8450    @bl      common_squeak4
8451    mov     r1, rINST, lsr #8           @ r1<- A+
8452    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8453    and     r1, r1, #15                 @ r1<- A
8454    cmp     r9, #0                      @ check object for null
8455    GET_VREG(r0, r1)                    @ r0<- fp[A]
8456    beq     common_errNullObject        @ object was null
8457    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8458    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8459    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8460    GOTO_OPCODE(ip)                     @ jump to next instruction
8461
8462
8463/* continuation for OP_SGET */
8464
8465    /*
8466     * Continuation if the field has not yet been resolved.
8467     *  r1: BBBB field ref
8468     */
8469.LOP_SGET_resolve:
8470    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8471    EXPORT_PC()                         @ resolve() could throw, so export now
8472    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8473    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8474    cmp     r0, #0                      @ success?
8475    bne     .LOP_SGET_finish          @ yes, finish
8476    b       common_exceptionThrown      @ no, handle exception
8477
8478
8479/* continuation for OP_SGET_WIDE */
8480
8481    /*
8482     * Continuation if the field has not yet been resolved.
8483     *  r1: BBBB field ref
8484     */
8485.LOP_SGET_WIDE_resolve:
8486    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8487    EXPORT_PC()                         @ resolve() could throw, so export now
8488    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8489    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8490    cmp     r0, #0                      @ success?
8491    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8492    b       common_exceptionThrown      @ no, handle exception
8493
8494
8495/* continuation for OP_SGET_OBJECT */
8496
8497    /*
8498     * Continuation if the field has not yet been resolved.
8499     *  r1: BBBB field ref
8500     */
8501.LOP_SGET_OBJECT_resolve:
8502    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8503    EXPORT_PC()                         @ resolve() could throw, so export now
8504    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8505    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8506    cmp     r0, #0                      @ success?
8507    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8508    b       common_exceptionThrown      @ no, handle exception
8509
8510
8511/* continuation for OP_SGET_BOOLEAN */
8512
8513    /*
8514     * Continuation if the field has not yet been resolved.
8515     *  r1: BBBB field ref
8516     */
8517.LOP_SGET_BOOLEAN_resolve:
8518    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8519    EXPORT_PC()                         @ resolve() could throw, so export now
8520    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8521    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8522    cmp     r0, #0                      @ success?
8523    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8524    b       common_exceptionThrown      @ no, handle exception
8525
8526
8527/* continuation for OP_SGET_BYTE */
8528
8529    /*
8530     * Continuation if the field has not yet been resolved.
8531     *  r1: BBBB field ref
8532     */
8533.LOP_SGET_BYTE_resolve:
8534    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8535    EXPORT_PC()                         @ resolve() could throw, so export now
8536    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8537    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8538    cmp     r0, #0                      @ success?
8539    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8540    b       common_exceptionThrown      @ no, handle exception
8541
8542
8543/* continuation for OP_SGET_CHAR */
8544
8545    /*
8546     * Continuation if the field has not yet been resolved.
8547     *  r1: BBBB field ref
8548     */
8549.LOP_SGET_CHAR_resolve:
8550    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8551    EXPORT_PC()                         @ resolve() could throw, so export now
8552    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8553    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8554    cmp     r0, #0                      @ success?
8555    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8556    b       common_exceptionThrown      @ no, handle exception
8557
8558
8559/* continuation for OP_SGET_SHORT */
8560
8561    /*
8562     * Continuation if the field has not yet been resolved.
8563     *  r1: BBBB field ref
8564     */
8565.LOP_SGET_SHORT_resolve:
8566    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8567    EXPORT_PC()                         @ resolve() could throw, so export now
8568    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8569    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8570    cmp     r0, #0                      @ success?
8571    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8572    b       common_exceptionThrown      @ no, handle exception
8573
8574
8575/* continuation for OP_SPUT */
8576
8577    /*
8578     * Continuation if the field has not yet been resolved.
8579     *  r1: BBBB field ref
8580     */
8581.LOP_SPUT_resolve:
8582    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8583    EXPORT_PC()                         @ resolve() could throw, so export now
8584    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8585    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8586    cmp     r0, #0                      @ success?
8587    bne     .LOP_SPUT_finish          @ yes, finish
8588    b       common_exceptionThrown      @ no, handle exception
8589
8590
8591/* continuation for OP_SPUT_WIDE */
8592
8593    /*
8594     * Continuation if the field has not yet been resolved.
8595     *  r1: BBBB field ref
8596     *  r9: &fp[AA]
8597     */
8598.LOP_SPUT_WIDE_resolve:
8599    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8600    EXPORT_PC()                         @ resolve() could throw, so export now
8601    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8602    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8603    cmp     r0, #0                      @ success?
8604    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8605    b       common_exceptionThrown      @ no, handle exception
8606
8607
8608/* continuation for OP_SPUT_OBJECT */
8609
8610    /*
8611     * Continuation if the field has not yet been resolved.
8612     *  r1: BBBB field ref
8613     */
8614.LOP_SPUT_OBJECT_resolve:
8615    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8616    EXPORT_PC()                         @ resolve() could throw, so export now
8617    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8618    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8619    cmp     r0, #0                      @ success?
8620    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8621    b       common_exceptionThrown      @ no, handle exception
8622
8623
8624/* continuation for OP_SPUT_BOOLEAN */
8625
8626    /*
8627     * Continuation if the field has not yet been resolved.
8628     *  r1: BBBB field ref
8629     */
8630.LOP_SPUT_BOOLEAN_resolve:
8631    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8632    EXPORT_PC()                         @ resolve() could throw, so export now
8633    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8634    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8635    cmp     r0, #0                      @ success?
8636    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8637    b       common_exceptionThrown      @ no, handle exception
8638
8639
8640/* continuation for OP_SPUT_BYTE */
8641
8642    /*
8643     * Continuation if the field has not yet been resolved.
8644     *  r1: BBBB field ref
8645     */
8646.LOP_SPUT_BYTE_resolve:
8647    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8648    EXPORT_PC()                         @ resolve() could throw, so export now
8649    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8650    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8651    cmp     r0, #0                      @ success?
8652    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8653    b       common_exceptionThrown      @ no, handle exception
8654
8655
8656/* continuation for OP_SPUT_CHAR */
8657
8658    /*
8659     * Continuation if the field has not yet been resolved.
8660     *  r1: BBBB field ref
8661     */
8662.LOP_SPUT_CHAR_resolve:
8663    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8664    EXPORT_PC()                         @ resolve() could throw, so export now
8665    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8666    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8667    cmp     r0, #0                      @ success?
8668    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8669    b       common_exceptionThrown      @ no, handle exception
8670
8671
8672/* continuation for OP_SPUT_SHORT */
8673
8674    /*
8675     * Continuation if the field has not yet been resolved.
8676     *  r1: BBBB field ref
8677     */
8678.LOP_SPUT_SHORT_resolve:
8679    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8680    EXPORT_PC()                         @ resolve() could throw, so export now
8681    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8682    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8683    cmp     r0, #0                      @ success?
8684    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8685    b       common_exceptionThrown      @ no, handle exception
8686
8687
8688/* continuation for OP_INVOKE_VIRTUAL */
8689
8690    /*
8691     * At this point:
8692     *  r0 = resolved base method
8693     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8694     */
8695.LOP_INVOKE_VIRTUAL_continue:
8696    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8697    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8698    cmp     r1, #0                      @ is "this" null?
8699    beq     common_errNullObject        @ null "this", throw exception
8700    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8701    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8702    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8703    bl      common_invokeMethodNoRange @ continue on
8704
8705
8706/* continuation for OP_INVOKE_SUPER */
8707
8708    /*
8709     * At this point:
8710     *  r0 = resolved base method
8711     *  r9 = method->clazz
8712     */
8713.LOP_INVOKE_SUPER_continue:
8714    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8715    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8716    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8717    EXPORT_PC()                         @ must export for invoke
8718    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8719    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8720    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8721    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8722    bl      common_invokeMethodNoRange @ continue on
8723
8724.LOP_INVOKE_SUPER_resolve:
8725    mov     r0, r9                      @ r0<- method->clazz
8726    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8727    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8728    cmp     r0, #0                      @ got null?
8729    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8730    b       common_exceptionThrown      @ yes, handle exception
8731
8732    /*
8733     * Throw a NoSuchMethodError with the method name as the message.
8734     *  r0 = resolved base method
8735     */
8736.LOP_INVOKE_SUPER_nsm:
8737    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8738    b       common_errNoSuchMethod
8739
8740
8741/* continuation for OP_INVOKE_DIRECT */
8742
8743    /*
8744     * On entry:
8745     *  r1 = reference (BBBB or CCCC)
8746     *  r10 = "this" register
8747     */
8748.LOP_INVOKE_DIRECT_resolve:
8749    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8750    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8751    mov     r2, #METHOD_DIRECT          @ resolver method type
8752    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8753    cmp     r0, #0                      @ got null?
8754    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8755    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8756    b       common_exceptionThrown      @ yes, handle exception
8757
8758
8759/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8760
8761    /*
8762     * At this point:
8763     *  r0 = resolved base method
8764     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8765     */
8766.LOP_INVOKE_VIRTUAL_RANGE_continue:
8767    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8768    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8769    cmp     r1, #0                      @ is "this" null?
8770    beq     common_errNullObject        @ null "this", throw exception
8771    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8772    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8773    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8774    bl      common_invokeMethodRange @ continue on
8775
8776
8777/* continuation for OP_INVOKE_SUPER_RANGE */
8778
8779    /*
8780     * At this point:
8781     *  r0 = resolved base method
8782     *  r9 = method->clazz
8783     */
8784.LOP_INVOKE_SUPER_RANGE_continue:
8785    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8786    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8787    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8788    EXPORT_PC()                         @ must export for invoke
8789    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8790    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8791    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8792    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8793    bl      common_invokeMethodRange @ continue on
8794
8795.LOP_INVOKE_SUPER_RANGE_resolve:
8796    mov     r0, r9                      @ r0<- method->clazz
8797    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8798    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8799    cmp     r0, #0                      @ got null?
8800    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8801    b       common_exceptionThrown      @ yes, handle exception
8802
8803    /*
8804     * Throw a NoSuchMethodError with the method name as the message.
8805     *  r0 = resolved base method
8806     */
8807.LOP_INVOKE_SUPER_RANGE_nsm:
8808    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8809    b       common_errNoSuchMethod
8810
8811
8812/* continuation for OP_INVOKE_DIRECT_RANGE */
8813
8814    /*
8815     * On entry:
8816     *  r1 = reference (BBBB or CCCC)
8817     *  r10 = "this" register
8818     */
8819.LOP_INVOKE_DIRECT_RANGE_resolve:
8820    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8821    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8822    mov     r2, #METHOD_DIRECT          @ resolver method type
8823    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8824    cmp     r0, #0                      @ got null?
8825    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8826    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8827    b       common_exceptionThrown      @ yes, handle exception
8828
8829
8830/* continuation for OP_FLOAT_TO_LONG */
8831/*
8832 * Convert the float in r0 to a long in r0/r1.
8833 *
8834 * We have to clip values to long min/max per the specification.  The
8835 * expected common case is a "reasonable" value that converts directly
8836 * to modest integer.  The EABI convert function isn't doing this for us.
8837 */
8838f2l_doconv:
8839    stmfd   sp!, {r4, lr}
8840    mov     r1, #0x5f000000             @ (float)maxlong
8841    mov     r4, r0
8842    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8843    cmp     r0, #0                      @ nonzero == yes
8844    mvnne   r0, #0                      @ return maxlong (7fffffff)
8845    mvnne   r1, #0x80000000
8846    ldmnefd sp!, {r4, pc}
8847
8848    mov     r0, r4                      @ recover arg
8849    mov     r1, #0xdf000000             @ (float)minlong
8850    bl      __aeabi_fcmple              @ is arg <= minlong?
8851    cmp     r0, #0                      @ nonzero == yes
8852    movne   r0, #0                      @ return minlong (80000000)
8853    movne   r1, #0x80000000
8854    ldmnefd sp!, {r4, pc}
8855
8856    mov     r0, r4                      @ recover arg
8857    mov     r1, r4
8858    bl      __aeabi_fcmpeq              @ is arg == self?
8859    cmp     r0, #0                      @ zero == no
8860    moveq   r1, #0                      @ return zero for NaN
8861    ldmeqfd sp!, {r4, pc}
8862
8863    mov     r0, r4                      @ recover arg
8864    bl      __aeabi_f2lz                @ convert float to long
8865    ldmfd   sp!, {r4, pc}
8866
8867
8868/* continuation for OP_DOUBLE_TO_LONG */
8869/*
8870 * Convert the double in r0/r1 to a long in r0/r1.
8871 *
8872 * We have to clip values to long min/max per the specification.  The
8873 * expected common case is a "reasonable" value that converts directly
8874 * to modest integer.  The EABI convert function isn't doing this for us.
8875 */
8876d2l_doconv:
8877    stmfd   sp!, {r4, r5, lr}           @ save regs
8878    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8879    add     r3, #0x00e00000             @  0x43e00000
8880    mov     r2, #0                      @ maxlong, as a double (low word)
8881    sub     sp, sp, #4                  @ align for EABI
8882    mov     r4, r0                      @ save a copy of r0
8883    mov     r5, r1                      @  and r1
8884    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8885    cmp     r0, #0                      @ nonzero == yes
8886    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8887    mvnne   r1, #0x80000000
8888    bne     1f
8889
8890    mov     r0, r4                      @ recover arg
8891    mov     r1, r5
8892    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8893    add     r3, #0x00e00000             @  0xc3e00000
8894    mov     r2, #0                      @ minlong, as a double (low word)
8895    bl      __aeabi_dcmple              @ is arg <= minlong?
8896    cmp     r0, #0                      @ nonzero == yes
8897    movne   r0, #0                      @ return minlong (8000000000000000)
8898    movne   r1, #0x80000000
8899    bne     1f
8900
8901    mov     r0, r4                      @ recover arg
8902    mov     r1, r5
8903    mov     r2, r4                      @ compare against self
8904    mov     r3, r5
8905    bl      __aeabi_dcmpeq              @ is arg == self?
8906    cmp     r0, #0                      @ zero == no
8907    moveq   r1, #0                      @ return zero for NaN
8908    beq     1f
8909
8910    mov     r0, r4                      @ recover arg
8911    mov     r1, r5
8912    bl      __aeabi_d2lz                @ convert double to long
8913
89141:
8915    add     sp, sp, #4
8916    ldmfd   sp!, {r4, r5, pc}
8917
8918
8919/* continuation for OP_MUL_LONG */
8920
8921.LOP_MUL_LONG_finish:
8922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8923    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8924    GOTO_OPCODE(ip)                     @ jump to next instruction
8925
8926
8927/* continuation for OP_SHL_LONG */
8928
8929.LOP_SHL_LONG_finish:
8930    mov     r0, r0, asl r2              @  r0<- r0 << r2
8931    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8932    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8933    GOTO_OPCODE(ip)                     @ jump to next instruction
8934
8935
8936/* continuation for OP_SHR_LONG */
8937
8938.LOP_SHR_LONG_finish:
8939    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8941    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8942    GOTO_OPCODE(ip)                     @ jump to next instruction
8943
8944
8945/* continuation for OP_USHR_LONG */
8946
8947.LOP_USHR_LONG_finish:
8948    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8949    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8950    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8951    GOTO_OPCODE(ip)                     @ jump to next instruction
8952
8953
8954/* continuation for OP_SHL_LONG_2ADDR */
8955
8956.LOP_SHL_LONG_2ADDR_finish:
8957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8958    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8959    GOTO_OPCODE(ip)                     @ jump to next instruction
8960
8961
8962/* continuation for OP_SHR_LONG_2ADDR */
8963
8964.LOP_SHR_LONG_2ADDR_finish:
8965    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8966    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8967    GOTO_OPCODE(ip)                     @ jump to next instruction
8968
8969
8970/* continuation for OP_USHR_LONG_2ADDR */
8971
8972.LOP_USHR_LONG_2ADDR_finish:
8973    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8974    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8975    GOTO_OPCODE(ip)                     @ jump to next instruction
8976
8977
8978/* continuation for OP_EXECUTE_INLINE */
8979
8980    /*
8981     * Extract args, call function.
8982     *  r0 = #of args (0-4)
8983     *  r10 = call index
8984     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8985     *
8986     * Other ideas:
8987     * - Use a jump table from the main piece to jump directly into the
8988     *   AND/LDR pairs.  Costs a data load, saves a branch.
8989     * - Have five separate pieces that do the loading, so we can work the
8990     *   interleave a little better.  Increases code size.
8991     */
8992.LOP_EXECUTE_INLINE_continue:
8993    rsb     r0, r0, #4                  @ r0<- 4-r0
8994    FETCH(r9, 2)                        @ r9<- FEDC
8995    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8996    bl      common_abort                @ (skipped due to ARM prefetch)
89974:  and     ip, r9, #0xf000             @ isolate F
8998    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89993:  and     ip, r9, #0x0f00             @ isolate E
9000    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
90012:  and     ip, r9, #0x00f0             @ isolate D
9002    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
90031:  and     ip, r9, #0x000f             @ isolate C
9004    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
90050:
9006    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9007    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9008    @ (not reached)
9009
9010.LOP_EXECUTE_INLINE_table:
9011    .word   gDvmInlineOpsTable
9012
9013
9014/* continuation for OP_EXECUTE_INLINE_RANGE */
9015
9016    /*
9017     * Extract args, call function.
9018     *  r0 = #of args (0-4)
9019     *  r10 = call index
9020     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9021     */
9022.LOP_EXECUTE_INLINE_RANGE_continue:
9023    rsb     r0, r0, #4                  @ r0<- 4-r0
9024    FETCH(r9, 2)                        @ r9<- CCCC
9025    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9026    bl      common_abort                @ (skipped due to ARM prefetch)
90274:  add     ip, r9, #3                  @ base+3
9028    GET_VREG(r3, ip)                    @ r3<- vBase[3]
90293:  add     ip, r9, #2                  @ base+2
9030    GET_VREG(r2, ip)                    @ r2<- vBase[2]
90312:  add     ip, r9, #1                  @ base+1
9032    GET_VREG(r1, ip)                    @ r1<- vBase[1]
90331:  add     ip, r9, #0                  @ (nop)
9034    GET_VREG(r0, ip)                    @ r0<- vBase[0]
90350:
9036    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9037    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9038    @ (not reached)
9039
9040.LOP_EXECUTE_INLINE_RANGE_table:
9041    .word   gDvmInlineOpsTable
9042
9043
9044    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9045    .global dvmAsmSisterEnd
9046dvmAsmSisterEnd:
9047
9048/* File: armv5te/footer.S */
9049
9050/*
9051 * ===========================================================================
9052 *  Common subroutines and data
9053 * ===========================================================================
9054 */
9055
9056
9057
9058    .text
9059    .align  2
9060
9061#if defined(WITH_JIT)
9062#if defined(WITH_SELF_VERIFICATION)
9063    .global dvmJitToInterpPunt
9064dvmJitToInterpPunt:
9065    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9066    b      dvmJitSelfVerificationEnd    @ doesn't return
9067
9068    .global dvmJitToInterpSingleStep
9069dvmJitToInterpSingleStep:
9070    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9071    b      dvmJitSelfVerificationEnd    @ doesn't return
9072
9073    .global dvmJitToTraceSelect
9074dvmJitToTraceSelect:
9075    ldr    r0,[lr, #-1]                 @ pass our target PC
9076    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9077    b      dvmJitSelfVerificationEnd    @ doesn't return
9078
9079    .global dvmJitToBackwardBranch
9080dvmJitToBackwardBranch:
9081    ldr    r0,[lr, #-1]                 @ pass our target PC
9082    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9083    b      dvmJitSelfVerificationEnd    @ doesn't return
9084
9085    .global dvmJitToInterpNormal
9086dvmJitToInterpNormal:
9087    ldr    r0,[lr, #-1]                 @ pass our target PC
9088    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9089    b      dvmJitSelfVerificationEnd    @ doesn't return
9090
9091    .global dvmJitToInterpNoChain
9092dvmJitToInterpNoChain:
9093    mov    r0,rPC                       @ pass our target PC
9094    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9095    b      dvmJitSelfVerificationEnd    @ doesn't return
9096#else
9097/*
9098 * Return from the translation cache to the interpreter when the compiler is
9099 * having issues translating/executing a Dalvik instruction. We have to skip
9100 * the code cache lookup otherwise it is possible to indefinitely bouce
9101 * between the interpreter and the code cache if the instruction that fails
9102 * to be compiled happens to be at a trace start.
9103 */
9104    .global dvmJitToInterpPunt
9105dvmJitToInterpPunt:
9106    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9107    mov    rPC, r0
9108#ifdef EXIT_STATS
9109    mov    r0,lr
9110    bl     dvmBumpPunt;
9111#endif
9112    EXPORT_PC()
9113    mov    r0, #0
9114    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9115    adrl   rIBASE, dvmAsmInstructionStart
9116    FETCH_INST()
9117    GET_INST_OPCODE(ip)
9118    GOTO_OPCODE(ip)
9119
9120/*
9121 * Return to the interpreter to handle a single instruction.
9122 * On entry:
9123 *    r0 <= PC
9124 *    r1 <= PC of resume instruction
9125 *    lr <= resume point in translation
9126 */
9127    .global dvmJitToInterpSingleStep
9128dvmJitToInterpSingleStep:
9129    str    lr,[rGLUE,#offGlue_jitResume]
9130    str    r1,[rGLUE,#offGlue_jitResumePC]
9131    mov    r1,#kInterpEntryInstr
9132    @ enum is 4 byte in aapcs-EABI
9133    str    r1, [rGLUE, #offGlue_entryPoint]
9134    mov    rPC,r0
9135    EXPORT_PC()
9136
9137    adrl   rIBASE, dvmAsmInstructionStart
9138    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9139    str    r2,[rGLUE,#offGlue_jitState]
9140    mov    r1,#1                  @ set changeInterp to bail to debug interp
9141    b      common_gotoBail
9142
9143
9144/*
9145 * Return from the translation cache and immediately request
9146 * a translation for the exit target.  Commonly used following
9147 * invokes.
9148 */
9149    .global dvmJitToTraceSelect
9150dvmJitToTraceSelect:
9151    ldr    rPC,[lr, #-1]           @ get our target PC
9152    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9153    add    rINST,lr,#-5            @ save start of chain branch
9154    mov    r0,rPC
9155    bl     dvmJitGetCodeAddr       @ Is there a translation?
9156    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9157    cmp    r0,#0
9158    beq    2f
9159    mov    r1,rINST
9160    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9161    mov    r1, rPC                  @ arg1 of translation may need this
9162    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9163    cmp    r0,#0                    @ successful chain?
9164    bxne   r0                       @ continue native execution
9165    b      toInterpreter            @ didn't chain - resume with interpreter
9166
9167/* No translation, so request one if profiling isn't disabled*/
91682:
9169    adrl   rIBASE, dvmAsmInstructionStart
9170    GET_JIT_PROF_TABLE(r0)
9171    FETCH_INST()
9172    cmp    r0, #0
9173    bne    common_selectTrace
9174    GET_INST_OPCODE(ip)
9175    GOTO_OPCODE(ip)
9176
9177/*
9178 * Return from the translation cache to the interpreter.
9179 * The return was done with a BLX from thumb mode, and
9180 * the following 32-bit word contains the target rPC value.
9181 * Note that lr (r14) will have its low-order bit set to denote
9182 * its thumb-mode origin.
9183 *
9184 * We'll need to stash our lr origin away, recover the new
9185 * target and then check to see if there is a translation available
9186 * for our new target.  If so, we do a translation chain and
9187 * go back to native execution.  Otherwise, it's back to the
9188 * interpreter (after treating this entry as a potential
9189 * trace start).
9190 */
9191    .global dvmJitToInterpNormal
9192dvmJitToInterpNormal:
9193    ldr    rPC,[lr, #-1]           @ get our target PC
9194    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9195    add    rINST,lr,#-5            @ save start of chain branch
9196#ifdef EXIT_STATS
9197    bl     dvmBumpNormal
9198#endif
9199    mov    r0,rPC
9200    bl     dvmJitGetCodeAddr        @ Is there a translation?
9201    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9202    cmp    r0,#0
9203    beq    toInterpreter            @ go if not, otherwise do chain
9204    mov    r1,rINST
9205    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9206    mov    r1, rPC                  @ arg1 of translation may need this
9207    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9208    cmp    r0,#0                    @ successful chain?
9209    bxne   r0                       @ continue native execution
9210    b      toInterpreter            @ didn't chain - resume with interpreter
9211
9212/*
9213 * Return from the translation cache to the interpreter to do method invocation.
9214 * Check if translation exists for the callee, but don't chain to it.
9215 */
9216    .global dvmJitToInterpNoChain
9217dvmJitToInterpNoChain:
9218#ifdef EXIT_STATS
9219    bl     dvmBumpNoChain
9220#endif
9221    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9222    mov    r0,rPC
9223    bl     dvmJitGetCodeAddr        @ Is there a translation?
9224    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9225    mov    r1, rPC                  @ arg1 of translation may need this
9226    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9227    cmp    r0,#0
9228    bxne   r0                       @ continue native execution if so
9229#endif
9230
9231/*
9232 * No translation, restore interpreter regs and start interpreting.
9233 * rGLUE & rFP were preserved in the translated code, and rPC has
9234 * already been restored by the time we get here.  We'll need to set
9235 * up rIBASE & rINST, and load the address of the JitTable into r0.
9236 */
9237toInterpreter:
9238    EXPORT_PC()
9239    adrl   rIBASE, dvmAsmInstructionStart
9240    FETCH_INST()
9241    GET_JIT_PROF_TABLE(r0)
9242    @ NOTE: intended fallthrough
9243/*
9244 * Common code to update potential trace start counter, and initiate
9245 * a trace-build if appropriate.  On entry, rPC should point to the
9246 * next instruction to execute, and rINST should be already loaded with
9247 * the next opcode word, and r0 holds a pointer to the jit profile
9248 * table (pJitProfTable).
9249 */
9250common_testUpdateProfile:
9251    cmp     r0,#0
9252    GET_INST_OPCODE(ip)
9253    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9254
9255common_updateProfile:
9256    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9257    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9258    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9259    GET_INST_OPCODE(ip)
9260    subs    r1,r1,#1           @ decrement counter
9261    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9262    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9263
9264/*
9265 * Here, we switch to the debug interpreter to request
9266 * trace selection.  First, though, check to see if there
9267 * is already a native translation in place (and, if so,
9268 * jump to it now).
9269 */
9270    GET_JIT_THRESHOLD(r1)
9271    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9272    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9273    EXPORT_PC()
9274    mov     r0,rPC
9275    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9276    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9277    mov     r1, rPC                     @ arg1 of translation may need this
9278    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9279    cmp     r0,#0
9280#if !defined(WITH_SELF_VERIFICATION)
9281    bxne    r0                          @ jump to the translation
9282#else
9283    beq     common_selectTrace
9284    /*
9285     * At this point, we have a target translation.  However, if
9286     * that translation is actually the interpret-only pseudo-translation
9287     * we want to treat it the same as no translation.
9288     */
9289    mov     r10, r0                      @ save target
9290    bl      dvmCompilerGetInterpretTemplate
9291    cmp     r0, r10                      @ special case?
9292    bne     dvmJitSelfVerificationStart  @ set up self verification
9293    GET_INST_OPCODE(ip)
9294    GOTO_OPCODE(ip)
9295    /* no return */
9296#endif
9297
9298common_selectTrace:
9299    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9300    str     r2,[rGLUE,#offGlue_jitState]
9301    mov     r2,#kInterpEntryInstr       @ normal entry reason
9302    str     r2,[rGLUE,#offGlue_entryPoint]
9303    mov     r1,#1                       @ set changeInterp
9304    b       common_gotoBail
9305
9306#if defined(WITH_SELF_VERIFICATION)
9307/*
9308 * Save PC and registers to shadow memory for self verification mode
9309 * before jumping to native translation.
9310 * On entry, r10 contains the address of the target translation.
9311 */
9312dvmJitSelfVerificationStart:
9313    mov     r0,rPC                      @ r0<- program counter
9314    mov     r1,rFP                      @ r1<- frame pointer
9315    mov     r2,rGLUE                    @ r2<- InterpState pointer
9316    mov     r3,r10                      @ r3<- target translation
9317    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9318    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9319    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9320    bx      r10                         @ jump to the translation
9321
9322/*
9323 * Restore PC, registers, and interpState to original values
9324 * before jumping back to the interpreter.
9325 */
9326dvmJitSelfVerificationEnd:
9327    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9328    mov    r1, #0
9329    str    r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9330    mov    r1,rFP                        @ pass ending fp
9331    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9332    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9333    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9334    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9335    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9336    cmp    r1,#0                         @ check for punt condition
9337    beq    1f
9338    mov    r2,#kJitSelfVerification      @ ask for self verification
9339    str    r2,[rGLUE,#offGlue_jitState]
9340    mov    r2,#kInterpEntryInstr         @ normal entry reason
9341    str    r2,[rGLUE,#offGlue_entryPoint]
9342    mov    r1,#1                         @ set changeInterp
9343    b      common_gotoBail
9344
93451:                                       @ exit to interpreter without check
9346    EXPORT_PC()
9347    adrl   rIBASE, dvmAsmInstructionStart
9348    FETCH_INST()
9349    GET_INST_OPCODE(ip)
9350    GOTO_OPCODE(ip)
9351#endif
9352
9353#endif
9354
9355/*
9356 * Common code when a backward branch is taken.
9357 *
9358 * On entry:
9359 *  r9 is PC adjustment *in bytes*
9360 */
9361common_backwardBranch:
9362    mov     r0, #kInterpEntryInstr
9363    bl      common_periodicChecks
9364#if defined(WITH_JIT)
9365    GET_JIT_PROF_TABLE(r0)
9366    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9367    cmp     r0,#0
9368    bne     common_updateProfile
9369    GET_INST_OPCODE(ip)
9370    GOTO_OPCODE(ip)
9371#else
9372    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9373    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9374    GOTO_OPCODE(ip)                     @ jump to next instruction
9375#endif
9376
9377
9378/*
9379 * Need to see if the thread needs to be suspended or debugger/profiler
9380 * activity has begun.
9381 *
9382 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9383 * have to do the second ldr.
9384 *
9385 * TODO: reduce this so we're just checking a single location.
9386 *
9387 * On entry:
9388 *  r0 is reentry type, e.g. kInterpEntryInstr
9389 *  r9 is trampoline PC adjustment *in bytes*
9390 */
9391common_periodicChecks:
9392    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9393
9394    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9395    str     r0, [rGLUE, #offGlue_entryPoint]
9396
9397#if defined(WITH_DEBUGGER)
9398    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9399#endif
9400#if defined(WITH_PROFILER)
9401    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9402#endif
9403
9404    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9405
9406#if defined(WITH_DEBUGGER)
9407    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9408#endif
9409#if defined (WITH_PROFILER)
9410    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9411#endif
9412
9413    cmp     r3, #0                      @ suspend pending?
9414    bne     2f                          @ yes, do full suspension check
9415
9416#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9417# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9418    orrs    r1, r1, r2                  @ r1<- r1 | r2
9419    cmp     r1, #0                      @ debugger attached or profiler started?
9420# elif defined(WITH_DEBUGGER)
9421    cmp     r1, #0                      @ debugger attached?
9422# elif defined(WITH_PROFILER)
9423    cmp     r2, #0                      @ profiler started?
9424# endif
9425    bne     3f                          @ debugger/profiler, switch interp
9426#endif
9427
9428    bx      lr                          @ nothing to do, return
9429
94302:  @ check suspend
9431#if defined(WITH_JIT)
9432    /*
9433     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9434     * doubles as the Jit's on/off switch.
9435     */
9436    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable
9437    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9438    ldr     r3, [r3] @ r10 <- pJitProfTable
9439    EXPORT_PC()                         @ need for precise GC
9440    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9441#else
9442    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9443    EXPORT_PC()                         @ need for precise GC
9444#endif
9445    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9446
94473:  @ debugger/profiler enabled, bail out
9448    add     rPC, rPC, r9                @ update rPC
9449    mov     r1, #1                      @ "want switch" = true
9450    b       common_gotoBail
9451
9452
9453/*
9454 * The equivalent of "goto bail", this calls through the "bail handler".
9455 *
9456 * State registers will be saved to the "glue" area before bailing.
9457 *
9458 * On entry:
9459 *  r1 is "bool changeInterp", indicating if we want to switch to the
9460 *     other interpreter or just bail all the way out
9461 */
9462common_gotoBail:
9463    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9464    mov     r0, rGLUE                   @ r0<- glue ptr
9465    b       dvmMterpStdBail             @ call(glue, changeInterp)
9466
9467    @add     r1, r1, #1                  @ using (boolean+1)
9468    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9469    @bl      _longjmp                    @ does not return
9470    @bl      common_abort
9471
9472
9473/*
9474 * Common code for method invocation with range.
9475 *
9476 * On entry:
9477 *  r0 is "Method* methodToCall", the method we're trying to call
9478 */
9479common_invokeMethodRange:
9480.LinvokeNewRange:
9481    @ prepare to copy args to "outs" area of current frame
9482    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9483    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9484    beq     .LinvokeArgsDone            @ if no args, skip the rest
9485    FETCH(r1, 2)                        @ r1<- CCCC
9486
9487    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9488    @ (very few methods have > 10 args; could unroll for common cases)
9489    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9490    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9491    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94921:  ldr     r1, [r3], #4                @ val = *fp++
9493    subs    r2, r2, #1                  @ count--
9494    str     r1, [r10], #4               @ *outs++ = val
9495    bne     1b                          @ ...while count != 0
9496    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9497    b       .LinvokeArgsDone
9498
9499/*
9500 * Common code for method invocation without range.
9501 *
9502 * On entry:
9503 *  r0 is "Method* methodToCall", the method we're trying to call
9504 */
9505common_invokeMethodNoRange:
9506.LinvokeNewNoRange:
9507    @ prepare to copy args to "outs" area of current frame
9508    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9509    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9510    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9511    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9512    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9513    beq     .LinvokeArgsDone
9514
9515    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9516.LinvokeNonRange:
9517    rsb     r2, r2, #5                  @ r2<- 5-r2
9518    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9519    bl      common_abort                @ (skipped due to ARM prefetch)
95205:  and     ip, rINST, #0x0f00          @ isolate A
9521    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9522    mov     r0, r0                      @ nop
9523    str     r2, [r10, #-4]!             @ *--outs = vA
95244:  and     ip, r1, #0xf000             @ isolate G
9525    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9526    mov     r0, r0                      @ nop
9527    str     r2, [r10, #-4]!             @ *--outs = vG
95283:  and     ip, r1, #0x0f00             @ isolate F
9529    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9530    mov     r0, r0                      @ nop
9531    str     r2, [r10, #-4]!             @ *--outs = vF
95322:  and     ip, r1, #0x00f0             @ isolate E
9533    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9534    mov     r0, r0                      @ nop
9535    str     r2, [r10, #-4]!             @ *--outs = vE
95361:  and     ip, r1, #0x000f             @ isolate D
9537    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9538    mov     r0, r0                      @ nop
9539    str     r2, [r10, #-4]!             @ *--outs = vD
95400:  @ fall through to .LinvokeArgsDone
9541
9542.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9543    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9544    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9545    @ find space for the new stack frame, check for overflow
9546    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9547    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9548    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9549@    bl      common_dumpRegs
9550    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9551    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9552    cmp     r3, r9                      @ bottom < interpStackEnd?
9553    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9554    blt     .LstackOverflow             @ yes, this frame will overflow stack
9555
9556    @ set up newSaveArea
9557#ifdef EASY_GDB
9558    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9559    str     ip, [r10, #offStackSaveArea_prevSave]
9560#endif
9561    str     rFP, [r10, #offStackSaveArea_prevFrame]
9562    str     rPC, [r10, #offStackSaveArea_savedPc]
9563#if defined(WITH_JIT)
9564    mov     r9, #0
9565    str     r9, [r10, #offStackSaveArea_returnAddr]
9566#endif
9567    str     r0, [r10, #offStackSaveArea_method]
9568    tst     r3, #ACC_NATIVE
9569    bne     .LinvokeNative
9570
9571    /*
9572    stmfd   sp!, {r0-r3}
9573    bl      common_printNewline
9574    mov     r0, rFP
9575    mov     r1, #0
9576    bl      dvmDumpFp
9577    ldmfd   sp!, {r0-r3}
9578    stmfd   sp!, {r0-r3}
9579    mov     r0, r1
9580    mov     r1, r10
9581    bl      dvmDumpFp
9582    bl      common_printNewline
9583    ldmfd   sp!, {r0-r3}
9584    */
9585
9586    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9587    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9588    mov     rPC, r2                         @ publish new rPC
9589    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9590
9591    @ Update "glue" values for the new method
9592    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9593    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9594    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9595#if defined(WITH_JIT)
9596    GET_JIT_PROF_TABLE(r0)
9597    mov     rFP, r1                         @ fp = newFp
9598    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9599    mov     rINST, r9                       @ publish new rINST
9600    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9601    cmp     r0,#0
9602    bne     common_updateProfile
9603    GOTO_OPCODE(ip)                         @ jump to next instruction
9604#else
9605    mov     rFP, r1                         @ fp = newFp
9606    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9607    mov     rINST, r9                       @ publish new rINST
9608    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9609    GOTO_OPCODE(ip)                         @ jump to next instruction
9610#endif
9611
9612.LinvokeNative:
9613    @ Prep for the native call
9614    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9615    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9616    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9617    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9618    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9619    mov     r9, r3                      @ r9<- glue->self (preserve)
9620
9621    mov     r2, r0                      @ r2<- methodToCall
9622    mov     r0, r1                      @ r0<- newFp (points to args)
9623    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9624
9625#ifdef ASSIST_DEBUGGER
9626    /* insert fake function header to help gdb find the stack frame */
9627    b       .Lskip
9628    .type   dalvik_mterp, %function
9629dalvik_mterp:
9630    .fnstart
9631    MTERP_ENTRY1
9632    MTERP_ENTRY2
9633.Lskip:
9634#endif
9635
9636    @mov     lr, pc                      @ set return addr
9637    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9638    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9639
9640#if defined(WITH_JIT)
9641    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9642#endif
9643
9644    @ native return; r9=self, r10=newSaveArea
9645    @ equivalent to dvmPopJniLocals
9646    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9647    ldr     r1, [r9, #offThread_exception] @ check for exception
9648#if defined(WITH_JIT)
9649    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9650#endif
9651    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9652    cmp     r1, #0                      @ null?
9653    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9654#if defined(WITH_JIT)
9655    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9656#endif
9657    bne     common_exceptionThrown      @ no, handle exception
9658
9659    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9660    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9661    GOTO_OPCODE(ip)                     @ jump to next instruction
9662
9663.LstackOverflow:    @ r0=methodToCall
9664    mov     r1, r0                      @ r1<- methodToCall
9665    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9666    bl      dvmHandleStackOverflow
9667    b       common_exceptionThrown
9668#ifdef ASSIST_DEBUGGER
9669    .fnend
9670#endif
9671
9672
9673    /*
9674     * Common code for method invocation, calling through "glue code".
9675     *
9676     * TODO: now that we have range and non-range invoke handlers, this
9677     *       needs to be split into two.  Maybe just create entry points
9678     *       that set r9 and jump here?
9679     *
9680     * On entry:
9681     *  r0 is "Method* methodToCall", the method we're trying to call
9682     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9683     */
9684     .if    0
9685.LinvokeOld:
9686    sub     sp, sp, #8                  @ space for args + pad
9687    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9688    mov     r2, r0                      @ A2<- methodToCall
9689    mov     r0, rGLUE                   @ A0<- glue
9690    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9691    mov     r1, r9                      @ A1<- methodCallRange
9692    mov     r3, rINST, lsr #8           @ A3<- AA
9693    str     ip, [sp, #0]                @ A4<- ip
9694    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9695    add     sp, sp, #8                  @ remove arg area
9696    b       common_resumeAfterGlueCall  @ continue to next instruction
9697    .endif
9698
9699
9700
9701/*
9702 * Common code for handling a return instruction.
9703 *
9704 * This does not return.
9705 */
9706common_returnFromMethod:
9707.LreturnNew:
9708    mov     r0, #kInterpEntryReturn
9709    mov     r9, #0
9710    bl      common_periodicChecks
9711
9712    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9713    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9714    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9715    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9716                                        @ r2<- method we're returning to
9717    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9718    cmp     r2, #0                      @ is this a break frame?
9719    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9720    mov     r1, #0                      @ "want switch" = false
9721    beq     common_gotoBail             @ break frame, bail out completely
9722
9723    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9724    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9725    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9726    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9727#if defined(WITH_JIT)
9728    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
9729    GET_JIT_PROF_TABLE(r0)
9730    mov     rPC, r9                     @ publish new rPC
9731    str     r1, [rGLUE, #offGlue_methodClassDex]
9732    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
9733    cmp     r10, #0                      @ caller is compiled code
9734    blxne   r10
9735    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9736    cmp     r0,#0
9737    bne     common_updateProfile
9738    GOTO_OPCODE(ip)                     @ jump to next instruction
9739#else
9740    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9741    mov     rPC, r9                     @ publish new rPC
9742    str     r1, [rGLUE, #offGlue_methodClassDex]
9743    GOTO_OPCODE(ip)                     @ jump to next instruction
9744#endif
9745
9746    /*
9747     * Return handling, calls through "glue code".
9748     */
9749     .if    0
9750.LreturnOld:
9751    SAVE_PC_FP_TO_GLUE()                @ export state
9752    mov     r0, rGLUE                   @ arg to function
9753    bl      dvmMterp_returnFromMethod
9754    b       common_resumeAfterGlueCall
9755    .endif
9756
9757
9758/*
9759 * Somebody has thrown an exception.  Handle it.
9760 *
9761 * If the exception processing code returns to us (instead of falling
9762 * out of the interpreter), continue with whatever the next instruction
9763 * now happens to be.
9764 *
9765 * This does not return.
9766 */
9767     .global dvmMterpCommonExceptionThrown
9768dvmMterpCommonExceptionThrown:
9769common_exceptionThrown:
9770.LexceptionNew:
9771    mov     r0, #kInterpEntryThrow
9772    mov     r9, #0
9773    bl      common_periodicChecks
9774
9775#if defined(WITH_JIT)
9776    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9777    str     r2,[rGLUE,#offGlue_jitState]
9778#endif
9779
9780    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9781    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9782    mov     r1, r10                     @ r1<- self
9783    mov     r0, r9                      @ r0<- exception
9784    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9785    mov     r3, #0                      @ r3<- NULL
9786    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9787
9788    /* set up args and a local for "&fp" */
9789    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9790    str     rFP, [sp, #-4]!             @ *--sp = fp
9791    mov     ip, sp                      @ ip<- &fp
9792    mov     r3, #0                      @ r3<- false
9793    str     ip, [sp, #-4]!              @ *--sp = &fp
9794    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9795    mov     r0, r10                     @ r0<- self
9796    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9797    mov     r2, r9                      @ r2<- exception
9798    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9799    mov     r1, r1, asr #1              @ r1<- offset in code units
9800
9801    /* call, r0 gets catchRelPc (a code-unit offset) */
9802    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9803
9804    /* fix earlier stack overflow if necessary; may trash rFP */
9805    ldrb    r1, [r10, #offThread_stackOverflowed]
9806    cmp     r1, #0                      @ did we overflow earlier?
9807    beq     1f                          @ no, skip ahead
9808    mov     rFP, r0                     @ save relPc result in rFP
9809    mov     r0, r10                     @ r0<- self
9810    mov     r1, r9                      @ r1<- exception
9811    bl      dvmCleanupStackOverflow     @ call(self)
9812    mov     r0, rFP                     @ restore result
98131:
9814
9815    /* update frame pointer and check result from dvmFindCatchBlock */
9816    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9817    cmp     r0, #0                      @ is catchRelPc < 0?
9818    add     sp, sp, #8                  @ restore stack
9819    bmi     .LnotCaughtLocally
9820
9821    /* adjust locals to match self->curFrame and updated PC */
9822    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9823    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9824    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9825    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9826    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9827    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9828    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9829    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9830
9831    /* release the tracked alloc on the exception */
9832    mov     r0, r9                      @ r0<- exception
9833    mov     r1, r10                     @ r1<- self
9834    bl      dvmReleaseTrackedAlloc      @ release the exception
9835
9836    /* restore the exception if the handler wants it */
9837    FETCH_INST()                        @ load rINST from rPC
9838    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9839    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9840    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9841    GOTO_OPCODE(ip)                     @ jump to next instruction
9842
9843.LnotCaughtLocally: @ r9=exception, r10=self
9844    /* fix stack overflow if necessary */
9845    ldrb    r1, [r10, #offThread_stackOverflowed]
9846    cmp     r1, #0                      @ did we overflow earlier?
9847    movne   r0, r10                     @ if yes: r0<- self
9848    movne   r1, r9                      @ if yes: r1<- exception
9849    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9850
9851    @ may want to show "not caught locally" debug messages here
9852#if DVM_SHOW_EXCEPTION >= 2
9853    /* call __android_log_print(prio, tag, format, ...) */
9854    /* "Exception %s from %s:%d not caught locally" */
9855    @ dvmLineNumFromPC(method, pc - method->insns)
9856    ldr     r0, [rGLUE, #offGlue_method]
9857    ldr     r1, [r0, #offMethod_insns]
9858    sub     r1, rPC, r1
9859    asr     r1, r1, #1
9860    bl      dvmLineNumFromPC
9861    str     r0, [sp, #-4]!
9862    @ dvmGetMethodSourceFile(method)
9863    ldr     r0, [rGLUE, #offGlue_method]
9864    bl      dvmGetMethodSourceFile
9865    str     r0, [sp, #-4]!
9866    @ exception->clazz->descriptor
9867    ldr     r3, [r9, #offObject_clazz]
9868    ldr     r3, [r3, #offClassObject_descriptor]
9869    @
9870    ldr     r2, strExceptionNotCaughtLocally
9871    ldr     r1, strLogTag
9872    mov     r0, #3                      @ LOG_DEBUG
9873    bl      __android_log_print
9874#endif
9875    str     r9, [r10, #offThread_exception] @ restore exception
9876    mov     r0, r9                      @ r0<- exception
9877    mov     r1, r10                     @ r1<- self
9878    bl      dvmReleaseTrackedAlloc      @ release the exception
9879    mov     r1, #0                      @ "want switch" = false
9880    b       common_gotoBail             @ bail out
9881
9882
9883    /*
9884     * Exception handling, calls through "glue code".
9885     */
9886    .if     0
9887.LexceptionOld:
9888    SAVE_PC_FP_TO_GLUE()                @ export state
9889    mov     r0, rGLUE                   @ arg to function
9890    bl      dvmMterp_exceptionThrown
9891    b       common_resumeAfterGlueCall
9892    .endif
9893
9894
9895/*
9896 * After returning from a "glued" function, pull out the updated
9897 * values and start executing at the next instruction.
9898 */
9899common_resumeAfterGlueCall:
9900    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9901    FETCH_INST()                        @ load rINST from rPC
9902    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9903    GOTO_OPCODE(ip)                     @ jump to next instruction
9904
9905/*
9906 * Invalid array index.
9907 */
9908common_errArrayIndex:
9909    EXPORT_PC()
9910    ldr     r0, strArrayIndexException
9911    mov     r1, #0
9912    bl      dvmThrowException
9913    b       common_exceptionThrown
9914
9915/*
9916 * Invalid array value.
9917 */
9918common_errArrayStore:
9919    EXPORT_PC()
9920    ldr     r0, strArrayStoreException
9921    mov     r1, #0
9922    bl      dvmThrowException
9923    b       common_exceptionThrown
9924
9925/*
9926 * Integer divide or mod by zero.
9927 */
9928common_errDivideByZero:
9929    EXPORT_PC()
9930    ldr     r0, strArithmeticException
9931    ldr     r1, strDivideByZero
9932    bl      dvmThrowException
9933    b       common_exceptionThrown
9934
9935/*
9936 * Attempt to allocate an array with a negative size.
9937 */
9938common_errNegativeArraySize:
9939    EXPORT_PC()
9940    ldr     r0, strNegativeArraySizeException
9941    mov     r1, #0
9942    bl      dvmThrowException
9943    b       common_exceptionThrown
9944
9945/*
9946 * Invocation of a non-existent method.
9947 */
9948common_errNoSuchMethod:
9949    EXPORT_PC()
9950    ldr     r0, strNoSuchMethodError
9951    mov     r1, #0
9952    bl      dvmThrowException
9953    b       common_exceptionThrown
9954
9955/*
9956 * We encountered a null object when we weren't expecting one.  We
9957 * export the PC, throw a NullPointerException, and goto the exception
9958 * processing code.
9959 */
9960common_errNullObject:
9961    EXPORT_PC()
9962    ldr     r0, strNullPointerException
9963    mov     r1, #0
9964    bl      dvmThrowException
9965    b       common_exceptionThrown
9966
9967/*
9968 * For debugging, cause an immediate fault.  The source address will
9969 * be in lr (use a bl instruction to jump here).
9970 */
9971common_abort:
9972    ldr     pc, .LdeadFood
9973.LdeadFood:
9974    .word   0xdeadf00d
9975
9976/*
9977 * Spit out a "we were here", preserving all registers.  (The attempt
9978 * to save ip won't work, but we need to save an even number of
9979 * registers for EABI 64-bit stack alignment.)
9980 */
9981    .macro  SQUEAK num
9982common_squeak\num:
9983    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9984    ldr     r0, strSqueak
9985    mov     r1, #\num
9986    bl      printf
9987    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9988    bx      lr
9989    .endm
9990
9991    SQUEAK  0
9992    SQUEAK  1
9993    SQUEAK  2
9994    SQUEAK  3
9995    SQUEAK  4
9996    SQUEAK  5
9997
9998/*
9999 * Spit out the number in r0, preserving registers.
10000 */
10001common_printNum:
10002    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10003    mov     r1, r0
10004    ldr     r0, strSqueak
10005    bl      printf
10006    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10007    bx      lr
10008
10009/*
10010 * Print a newline, preserving registers.
10011 */
10012common_printNewline:
10013    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10014    ldr     r0, strNewline
10015    bl      printf
10016    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10017    bx      lr
10018
10019    /*
10020     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10021     */
10022common_printHex:
10023    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10024    mov     r1, r0
10025    ldr     r0, strPrintHex
10026    bl      printf
10027    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10028    bx      lr
10029
10030/*
10031 * Print the 64-bit quantity in r0-r1, preserving registers.
10032 */
10033common_printLong:
10034    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10035    mov     r3, r1
10036    mov     r2, r0
10037    ldr     r0, strPrintLong
10038    bl      printf
10039    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10040    bx      lr
10041
10042/*
10043 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10044 */
10045common_printMethod:
10046    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10047    bl      dvmMterpPrintMethod
10048    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10049    bx      lr
10050
10051/*
10052 * Call a C helper function that dumps regs and possibly some
10053 * additional info.  Requires the C function to be compiled in.
10054 */
10055    .if     0
10056common_dumpRegs:
10057    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10058    bl      dvmMterpDumpArmRegs
10059    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10060    bx      lr
10061    .endif
10062
10063#if 0
10064/*
10065 * Experiment on VFP mode.
10066 *
10067 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10068 *
10069 * Updates the bits specified by "mask", setting them to the values in "val".
10070 */
10071setFPSCR:
10072    and     r0, r0, r1                  @ make sure no stray bits are set
10073    fmrx    r2, fpscr                   @ get VFP reg
10074    mvn     r1, r1                      @ bit-invert mask
10075    and     r2, r2, r1                  @ clear masked bits
10076    orr     r2, r2, r0                  @ set specified bits
10077    fmxr    fpscr, r2                   @ set VFP reg
10078    mov     r0, r2                      @ return new value
10079    bx      lr
10080
10081    .align  2
10082    .global dvmConfigureFP
10083    .type   dvmConfigureFP, %function
10084dvmConfigureFP:
10085    stmfd   sp!, {ip, lr}
10086    /* 0x03000000 sets DN/FZ */
10087    /* 0x00009f00 clears the six exception enable flags */
10088    bl      common_squeak0
10089    mov     r0, #0x03000000             @ r0<- 0x03000000
10090    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10091    bl      setFPSCR
10092    ldmfd   sp!, {ip, pc}
10093#endif
10094
10095
10096/*
10097 * String references, must be close to the code that uses them.
10098 */
10099    .align  2
10100strArithmeticException:
10101    .word   .LstrArithmeticException
10102strArrayIndexException:
10103    .word   .LstrArrayIndexException
10104strArrayStoreException:
10105    .word   .LstrArrayStoreException
10106strDivideByZero:
10107    .word   .LstrDivideByZero
10108strNegativeArraySizeException:
10109    .word   .LstrNegativeArraySizeException
10110strNoSuchMethodError:
10111    .word   .LstrNoSuchMethodError
10112strNullPointerException:
10113    .word   .LstrNullPointerException
10114
10115strLogTag:
10116    .word   .LstrLogTag
10117strExceptionNotCaughtLocally:
10118    .word   .LstrExceptionNotCaughtLocally
10119
10120strNewline:
10121    .word   .LstrNewline
10122strSqueak:
10123    .word   .LstrSqueak
10124strPrintHex:
10125    .word   .LstrPrintHex
10126strPrintLong:
10127    .word   .LstrPrintLong
10128
10129/*
10130 * Zero-terminated ASCII string data.
10131 *
10132 * On ARM we have two choices: do like gcc does, and LDR from a .word
10133 * with the address, or use an ADR pseudo-op to get the address
10134 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10135 * PC-relative addressing mode and hence has a limited range, which
10136 * makes it not work well with mergeable string sections.
10137 */
10138    .section .rodata.str1.4,"aMS",%progbits,1
10139
10140.LstrBadEntryPoint:
10141    .asciz  "Bad entry point %d\n"
10142.LstrArithmeticException:
10143    .asciz  "Ljava/lang/ArithmeticException;"
10144.LstrArrayIndexException:
10145    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10146.LstrArrayStoreException:
10147    .asciz  "Ljava/lang/ArrayStoreException;"
10148.LstrClassCastException:
10149    .asciz  "Ljava/lang/ClassCastException;"
10150.LstrDivideByZero:
10151    .asciz  "divide by zero"
10152.LstrFilledNewArrayNotImpl:
10153    .asciz  "filled-new-array only implemented for objects and 'int'"
10154.LstrInternalError:
10155    .asciz  "Ljava/lang/InternalError;"
10156.LstrInstantiationError:
10157    .asciz  "Ljava/lang/InstantiationError;"
10158.LstrNegativeArraySizeException:
10159    .asciz  "Ljava/lang/NegativeArraySizeException;"
10160.LstrNoSuchMethodError:
10161    .asciz  "Ljava/lang/NoSuchMethodError;"
10162.LstrNullPointerException:
10163    .asciz  "Ljava/lang/NullPointerException;"
10164
10165.LstrLogTag:
10166    .asciz  "mterp"
10167.LstrExceptionNotCaughtLocally:
10168    .asciz  "Exception %s from %s:%d not caught locally\n"
10169
10170.LstrNewline:
10171    .asciz  "\n"
10172.LstrSqueak:
10173    .asciz  "<%d>"
10174.LstrPrintHex:
10175    .asciz  "<0x%x>"
10176.LstrPrintLong:
10177    .asciz  "<%lld>"
10178
10179
10180