InterpAsm-armv7-a.S revision 7b133ef7c84e68c3c4042176d830ea5b52e84139
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
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: armv6t2/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    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
429    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
430    GET_VREG(r2, r1)                    @ r2<- fp[B]
431    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
432    SET_VREG(r2, r0)                    @ fp[A]<- r2
433    GOTO_OPCODE(ip)                     @ execute next instruction
434
435
436/* ------------------------------ */
437    .balign 64
438.L_OP_MOVE_FROM16: /* 0x02 */
439/* File: armv5te/OP_MOVE_FROM16.S */
440    /* for: move/from16, move-object/from16 */
441    /* op vAA, vBBBB */
442    FETCH(r1, 1)                        @ r1<- BBBB
443    mov     r0, rINST, lsr #8           @ r0<- AA
444    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
445    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
446    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
447    SET_VREG(r2, r0)                    @ fp[AA]<- r2
448    GOTO_OPCODE(ip)                     @ jump to next instruction
449
450
451/* ------------------------------ */
452    .balign 64
453.L_OP_MOVE_16: /* 0x03 */
454/* File: armv5te/OP_MOVE_16.S */
455    /* for: move/16, move-object/16 */
456    /* op vAAAA, vBBBB */
457    FETCH(r1, 2)                        @ r1<- BBBB
458    FETCH(r0, 1)                        @ r0<- AAAA
459    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
460    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
461    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
462    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
463    GOTO_OPCODE(ip)                     @ jump to next instruction
464
465
466/* ------------------------------ */
467    .balign 64
468.L_OP_MOVE_WIDE: /* 0x04 */
469/* File: armv6t2/OP_MOVE_WIDE.S */
470    /* move-wide vA, vB */
471    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
472    mov     r3, rINST, lsr #12          @ r3<- B
473    ubfx    r2, rINST, #8, #4           @ r2<- A
474    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
475    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
476    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
477    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
478    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
479    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
480    GOTO_OPCODE(ip)                     @ jump to next instruction
481
482
483/* ------------------------------ */
484    .balign 64
485.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
486/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
487    /* move-wide/from16 vAA, vBBBB */
488    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
489    FETCH(r3, 1)                        @ r3<- BBBB
490    mov     r2, rINST, lsr #8           @ r2<- AA
491    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
492    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
493    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
496    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
497    GOTO_OPCODE(ip)                     @ jump to next instruction
498
499
500/* ------------------------------ */
501    .balign 64
502.L_OP_MOVE_WIDE_16: /* 0x06 */
503/* File: armv5te/OP_MOVE_WIDE_16.S */
504    /* move-wide/16 vAAAA, vBBBB */
505    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
506    FETCH(r3, 2)                        @ r3<- BBBB
507    FETCH(r2, 1)                        @ r2<- AAAA
508    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
509    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
510    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
511    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
513    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
514    GOTO_OPCODE(ip)                     @ jump to next instruction
515
516
517/* ------------------------------ */
518    .balign 64
519.L_OP_MOVE_OBJECT: /* 0x07 */
520/* File: armv5te/OP_MOVE_OBJECT.S */
521/* File: armv5te/OP_MOVE.S */
522    /* for move, move-object, long-to-int */
523    /* op vA, vB */
524    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
525    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
526    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
527    GET_VREG(r2, r1)                    @ r2<- fp[B]
528    and     r0, r0, #15
529    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
530    SET_VREG(r2, r0)                    @ fp[A]<- r2
531    GOTO_OPCODE(ip)                     @ execute next instruction
532
533
534
535/* ------------------------------ */
536    .balign 64
537.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
538/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
539/* File: armv5te/OP_MOVE_FROM16.S */
540    /* for: move/from16, move-object/from16 */
541    /* op vAA, vBBBB */
542    FETCH(r1, 1)                        @ r1<- BBBB
543    mov     r0, rINST, lsr #8           @ r0<- AA
544    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
545    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
547    SET_VREG(r2, r0)                    @ fp[AA]<- r2
548    GOTO_OPCODE(ip)                     @ jump to next instruction
549
550
551
552/* ------------------------------ */
553    .balign 64
554.L_OP_MOVE_OBJECT_16: /* 0x09 */
555/* File: armv5te/OP_MOVE_OBJECT_16.S */
556/* File: armv5te/OP_MOVE_16.S */
557    /* for: move/16, move-object/16 */
558    /* op vAAAA, vBBBB */
559    FETCH(r1, 2)                        @ r1<- BBBB
560    FETCH(r0, 1)                        @ r0<- AAAA
561    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
562    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
564    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
565    GOTO_OPCODE(ip)                     @ jump to next instruction
566
567
568
569/* ------------------------------ */
570    .balign 64
571.L_OP_MOVE_RESULT: /* 0x0a */
572/* File: armv5te/OP_MOVE_RESULT.S */
573    /* for: move-result, move-result-object */
574    /* op vAA */
575    mov     r2, rINST, lsr #8           @ r2<- AA
576    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
577    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
578    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
579    SET_VREG(r0, r2)                    @ fp[AA]<- r0
580    GOTO_OPCODE(ip)                     @ jump to next instruction
581
582
583/* ------------------------------ */
584    .balign 64
585.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
586/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
587    /* move-result-wide vAA */
588    mov     r2, rINST, lsr #8           @ r2<- AA
589    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
590    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
591    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
594    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
595    GOTO_OPCODE(ip)                     @ jump to next instruction
596
597
598/* ------------------------------ */
599    .balign 64
600.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
601/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
602/* File: armv5te/OP_MOVE_RESULT.S */
603    /* for: move-result, move-result-object */
604    /* op vAA */
605    mov     r2, rINST, lsr #8           @ r2<- AA
606    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
607    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
608    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
609    SET_VREG(r0, r2)                    @ fp[AA]<- r0
610    GOTO_OPCODE(ip)                     @ jump to next instruction
611
612
613
614/* ------------------------------ */
615    .balign 64
616.L_OP_MOVE_EXCEPTION: /* 0x0d */
617/* File: armv5te/OP_MOVE_EXCEPTION.S */
618    /* move-exception vAA */
619    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
620    mov     r2, rINST, lsr #8           @ r2<- AA
621    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
622    mov     r1, #0                      @ r1<- 0
623    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
624    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
626    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
627    GOTO_OPCODE(ip)                     @ jump to next instruction
628
629
630/* ------------------------------ */
631    .balign 64
632.L_OP_RETURN_VOID: /* 0x0e */
633/* File: armv5te/OP_RETURN_VOID.S */
634    b       common_returnFromMethod
635
636
637/* ------------------------------ */
638    .balign 64
639.L_OP_RETURN: /* 0x0f */
640/* File: armv5te/OP_RETURN.S */
641    /*
642     * Return a 32-bit value.  Copies the return value into the "glue"
643     * structure, then jumps to the return handler.
644     *
645     * for: return, return-object
646     */
647    /* op vAA */
648    mov     r2, rINST, lsr #8           @ r2<- AA
649    GET_VREG(r0, r2)                    @ r0<- vAA
650    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
651    b       common_returnFromMethod
652
653
654/* ------------------------------ */
655    .balign 64
656.L_OP_RETURN_WIDE: /* 0x10 */
657/* File: armv5te/OP_RETURN_WIDE.S */
658    /*
659     * Return a 64-bit value.  Copies the return value into the "glue"
660     * structure, then jumps to the return handler.
661     */
662    /* return-wide vAA */
663    mov     r2, rINST, lsr #8           @ r2<- AA
664    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
665    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
666    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
667    stmia   r3, {r0-r1}                 @ retval<- r0/r1
668    b       common_returnFromMethod
669
670
671/* ------------------------------ */
672    .balign 64
673.L_OP_RETURN_OBJECT: /* 0x11 */
674/* File: armv5te/OP_RETURN_OBJECT.S */
675/* File: armv5te/OP_RETURN.S */
676    /*
677     * Return a 32-bit value.  Copies the return value into the "glue"
678     * structure, then jumps to the return handler.
679     *
680     * for: return, return-object
681     */
682    /* op vAA */
683    mov     r2, rINST, lsr #8           @ r2<- AA
684    GET_VREG(r0, r2)                    @ r0<- vAA
685    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
686    b       common_returnFromMethod
687
688
689
690/* ------------------------------ */
691    .balign 64
692.L_OP_CONST_4: /* 0x12 */
693/* File: armv6t2/OP_CONST_4.S */
694    /* const/4 vA, #+B */
695    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
696    ubfx    r0, rINST, #8, #4           @ r0<- A
697    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
698    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
699    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
700    SET_VREG(r1, r0)                    @ fp[A]<- r1
701    GOTO_OPCODE(ip)                     @ execute next instruction
702
703
704/* ------------------------------ */
705    .balign 64
706.L_OP_CONST_16: /* 0x13 */
707/* File: armv5te/OP_CONST_16.S */
708    /* const/16 vAA, #+BBBB */
709    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
710    mov     r3, rINST, lsr #8           @ r3<- AA
711    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
712    SET_VREG(r0, r3)                    @ vAA<- r0
713    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
714    GOTO_OPCODE(ip)                     @ jump to next instruction
715
716
717/* ------------------------------ */
718    .balign 64
719.L_OP_CONST: /* 0x14 */
720/* File: armv5te/OP_CONST.S */
721    /* const vAA, #+BBBBbbbb */
722    mov     r3, rINST, lsr #8           @ r3<- AA
723    FETCH(r0, 1)                        @ r0<- bbbb (low)
724    FETCH(r1, 2)                        @ r1<- BBBB (high)
725    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
726    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
727    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
728    SET_VREG(r0, r3)                    @ vAA<- r0
729    GOTO_OPCODE(ip)                     @ jump to next instruction
730
731
732/* ------------------------------ */
733    .balign 64
734.L_OP_CONST_HIGH16: /* 0x15 */
735/* File: armv5te/OP_CONST_HIGH16.S */
736    /* const/high16 vAA, #+BBBB0000 */
737    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
738    mov     r3, rINST, lsr #8           @ r3<- AA
739    mov     r0, r0, lsl #16             @ r0<- BBBB0000
740    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
741    SET_VREG(r0, r3)                    @ vAA<- r0
742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
743    GOTO_OPCODE(ip)                     @ jump to next instruction
744
745
746/* ------------------------------ */
747    .balign 64
748.L_OP_CONST_WIDE_16: /* 0x16 */
749/* File: armv5te/OP_CONST_WIDE_16.S */
750    /* const-wide/16 vAA, #+BBBB */
751    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
752    mov     r3, rINST, lsr #8           @ r3<- AA
753    mov     r1, r0, asr #31             @ r1<- ssssssss
754    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
755    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
757    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
758    GOTO_OPCODE(ip)                     @ jump to next instruction
759
760
761/* ------------------------------ */
762    .balign 64
763.L_OP_CONST_WIDE_32: /* 0x17 */
764/* File: armv5te/OP_CONST_WIDE_32.S */
765    /* const-wide/32 vAA, #+BBBBbbbb */
766    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
767    mov     r3, rINST, lsr #8           @ r3<- AA
768    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
769    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
770    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
771    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
772    mov     r1, r0, asr #31             @ r1<- ssssssss
773    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
774    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
775    GOTO_OPCODE(ip)                     @ jump to next instruction
776
777
778/* ------------------------------ */
779    .balign 64
780.L_OP_CONST_WIDE: /* 0x18 */
781/* File: armv5te/OP_CONST_WIDE.S */
782    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
783    FETCH(r0, 1)                        @ r0<- bbbb (low)
784    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
785    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
786    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
787    FETCH(r3, 4)                        @ r3<- HHHH (high)
788    mov     r9, rINST, lsr #8           @ r9<- AA
789    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
790    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
791    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
793    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
794    GOTO_OPCODE(ip)                     @ jump to next instruction
795
796
797/* ------------------------------ */
798    .balign 64
799.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
800/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
801    /* const-wide/high16 vAA, #+BBBB000000000000 */
802    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
803    mov     r3, rINST, lsr #8           @ r3<- AA
804    mov     r0, #0                      @ r0<- 00000000
805    mov     r1, r1, lsl #16             @ r1<- BBBB0000
806    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
807    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
809    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
810    GOTO_OPCODE(ip)                     @ jump to next instruction
811
812
813/* ------------------------------ */
814    .balign 64
815.L_OP_CONST_STRING: /* 0x1a */
816/* File: armv5te/OP_CONST_STRING.S */
817    /* const/string vAA, String@BBBB */
818    FETCH(r1, 1)                        @ r1<- BBBB
819    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
820    mov     r9, rINST, lsr #8           @ r9<- AA
821    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
822    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
823    cmp     r0, #0                      @ not yet resolved?
824    beq     .LOP_CONST_STRING_resolve
825    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
827    SET_VREG(r0, r9)                    @ vAA<- r0
828    GOTO_OPCODE(ip)                     @ jump to next instruction
829
830/* ------------------------------ */
831    .balign 64
832.L_OP_CONST_STRING_JUMBO: /* 0x1b */
833/* File: armv5te/OP_CONST_STRING_JUMBO.S */
834    /* const/string vAA, String@BBBBBBBB */
835    FETCH(r0, 1)                        @ r0<- bbbb (low)
836    FETCH(r1, 2)                        @ r1<- BBBB (high)
837    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
838    mov     r9, rINST, lsr #8           @ r9<- AA
839    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
840    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
841    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
842    cmp     r0, #0
843    beq     .LOP_CONST_STRING_JUMBO_resolve
844    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
845    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
846    SET_VREG(r0, r9)                    @ vAA<- r0
847    GOTO_OPCODE(ip)                     @ jump to next instruction
848
849/* ------------------------------ */
850    .balign 64
851.L_OP_CONST_CLASS: /* 0x1c */
852/* File: armv5te/OP_CONST_CLASS.S */
853    /* const/class vAA, Class@BBBB */
854    FETCH(r1, 1)                        @ r1<- BBBB
855    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
856    mov     r9, rINST, lsr #8           @ r9<- AA
857    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
858    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
859    cmp     r0, #0                      @ not yet resolved?
860    beq     .LOP_CONST_CLASS_resolve
861    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
863    SET_VREG(r0, r9)                    @ vAA<- r0
864    GOTO_OPCODE(ip)                     @ jump to next instruction
865
866/* ------------------------------ */
867    .balign 64
868.L_OP_MONITOR_ENTER: /* 0x1d */
869/* File: armv5te/OP_MONITOR_ENTER.S */
870    /*
871     * Synchronize on an object.
872     */
873    /* monitor-enter vAA */
874    mov     r2, rINST, lsr #8           @ r2<- AA
875    GET_VREG(r1, r2)                    @ r1<- vAA (object)
876    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
877    cmp     r1, #0                      @ null object?
878    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
879    beq     common_errNullObject        @ null object, throw an exception
880    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
881    bl      dvmLockObject               @ call(self, obj)
882#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
883    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
884    ldr     r1, [r0, #offThread_exception] @ check for exception
885    cmp     r1, #0
886    bne     common_exceptionThrown      @ exception raised, bail out
887#endif
888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
889    GOTO_OPCODE(ip)                     @ jump to next instruction
890
891
892/* ------------------------------ */
893    .balign 64
894.L_OP_MONITOR_EXIT: /* 0x1e */
895/* File: armv5te/OP_MONITOR_EXIT.S */
896    /*
897     * Unlock an object.
898     *
899     * Exceptions that occur when unlocking a monitor need to appear as
900     * if they happened at the following instruction.  See the Dalvik
901     * instruction spec.
902     */
903    /* monitor-exit vAA */
904    mov     r2, rINST, lsr #8           @ r2<- AA
905    EXPORT_PC()                         @ before fetch: export the PC
906    GET_VREG(r1, r2)                    @ r1<- vAA (object)
907    cmp     r1, #0                      @ null object?
908    beq     common_errNullObject        @ yes
909    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
910    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
911    cmp     r0, #0                      @ failed?
912    beq     common_exceptionThrown      @ yes, exception is pending
913    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
914    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
915    GOTO_OPCODE(ip)                     @ jump to next instruction
916
917
918/* ------------------------------ */
919    .balign 64
920.L_OP_CHECK_CAST: /* 0x1f */
921/* File: armv5te/OP_CHECK_CAST.S */
922    /*
923     * Check to see if a cast from one class to another is allowed.
924     */
925    /* check-cast vAA, class@BBBB */
926    mov     r3, rINST, lsr #8           @ r3<- AA
927    FETCH(r2, 1)                        @ r2<- BBBB
928    GET_VREG(r9, r3)                    @ r9<- object
929    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
930    cmp     r9, #0                      @ is object null?
931    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
932    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
933    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
934    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
935    cmp     r1, #0                      @ have we resolved this before?
936    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
937.LOP_CHECK_CAST_resolved:
938    cmp     r0, r1                      @ same class (trivial success)?
939    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
940.LOP_CHECK_CAST_okay:
941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
942    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
943    GOTO_OPCODE(ip)                     @ jump to next instruction
944
945/* ------------------------------ */
946    .balign 64
947.L_OP_INSTANCE_OF: /* 0x20 */
948/* File: armv5te/OP_INSTANCE_OF.S */
949    /*
950     * Check to see if an object reference is an instance of a class.
951     *
952     * Most common situation is a non-null object, being compared against
953     * an already-resolved class.
954     */
955    /* instance-of vA, vB, class@CCCC */
956    mov     r3, rINST, lsr #12          @ r3<- B
957    mov     r9, rINST, lsr #8           @ r9<- A+
958    GET_VREG(r0, r3)                    @ r0<- vB (object)
959    and     r9, r9, #15                 @ r9<- A
960    cmp     r0, #0                      @ is object null?
961    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
962    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
963    FETCH(r3, 1)                        @ r3<- CCCC
964    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
965    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
966    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
967    cmp     r1, #0                      @ have we resolved this before?
968    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
969.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
970    cmp     r0, r1                      @ same class (trivial success)?
971    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
972    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
973
974/* ------------------------------ */
975    .balign 64
976.L_OP_ARRAY_LENGTH: /* 0x21 */
977/* File: armv6t2/OP_ARRAY_LENGTH.S */
978    /*
979     * Return the length of an array.
980     */
981    mov     r1, rINST, lsr #12          @ r1<- B
982    ubfx    r2, rINST, #8, #4           @ r2<- A
983    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
984    cmp     r0, #0                      @ is object null?
985    beq     common_errNullObject        @ yup, fail
986    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
987    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
989    SET_VREG(r3, r2)                    @ vB<- length
990    GOTO_OPCODE(ip)                     @ jump to next instruction
991
992
993/* ------------------------------ */
994    .balign 64
995.L_OP_NEW_INSTANCE: /* 0x22 */
996/* File: armv5te/OP_NEW_INSTANCE.S */
997    /*
998     * Create a new instance of a class.
999     */
1000    /* new-instance vAA, class@BBBB */
1001    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1002    FETCH(r1, 1)                        @ r1<- BBBB
1003    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1004    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1005    EXPORT_PC()                         @ req'd for init, resolve, alloc
1006    cmp     r0, #0                      @ already resolved?
1007    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1008.LOP_NEW_INSTANCE_resolved:   @ r0=class
1009    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1010    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1011    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1012.LOP_NEW_INSTANCE_initialized: @ r0=class
1013    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1014    bl      dvmAllocObject              @ r0<- new object
1015    b       .LOP_NEW_INSTANCE_finish          @ continue
1016
1017/* ------------------------------ */
1018    .balign 64
1019.L_OP_NEW_ARRAY: /* 0x23 */
1020/* File: armv5te/OP_NEW_ARRAY.S */
1021    /*
1022     * Allocate an array of objects, specified with the array class
1023     * and a count.
1024     *
1025     * The verifier guarantees that this is an array class, so we don't
1026     * check for it here.
1027     */
1028    /* new-array vA, vB, class@CCCC */
1029    mov     r0, rINST, lsr #12          @ r0<- B
1030    FETCH(r2, 1)                        @ r2<- CCCC
1031    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1032    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1033    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1034    cmp     r1, #0                      @ check length
1035    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1036    bmi     common_errNegativeArraySize @ negative length, bail
1037    cmp     r0, #0                      @ already resolved?
1038    EXPORT_PC()                         @ req'd for resolve, alloc
1039    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1040    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1041
1042/* ------------------------------ */
1043    .balign 64
1044.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1045/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1046    /*
1047     * Create a new array with elements filled from registers.
1048     *
1049     * for: filled-new-array, filled-new-array/range
1050     */
1051    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1052    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1053    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1054    FETCH(r1, 1)                        @ r1<- BBBB
1055    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1056    EXPORT_PC()                         @ need for resolve and alloc
1057    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1058    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1059    cmp     r0, #0                      @ already resolved?
1060    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10618:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1062    mov     r2, #0                      @ r2<- false
1063    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1064    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1065    cmp     r0, #0                      @ got null?
1066    beq     common_exceptionThrown      @ yes, handle exception
1067    b       .LOP_FILLED_NEW_ARRAY_continue
1068
1069/* ------------------------------ */
1070    .balign 64
1071.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1072/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1073/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1074    /*
1075     * Create a new array with elements filled from registers.
1076     *
1077     * for: filled-new-array, filled-new-array/range
1078     */
1079    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1080    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1081    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1082    FETCH(r1, 1)                        @ r1<- BBBB
1083    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1084    EXPORT_PC()                         @ need for resolve and alloc
1085    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1086    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1087    cmp     r0, #0                      @ already resolved?
1088    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10898:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1090    mov     r2, #0                      @ r2<- false
1091    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1092    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1093    cmp     r0, #0                      @ got null?
1094    beq     common_exceptionThrown      @ yes, handle exception
1095    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1096
1097
1098/* ------------------------------ */
1099    .balign 64
1100.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1101/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1102    /* fill-array-data vAA, +BBBBBBBB */
1103    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1104    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1105    mov     r3, rINST, lsr #8           @ r3<- AA
1106    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1107    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1108    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1109    EXPORT_PC();
1110    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1111    cmp     r0, #0                      @ 0 means an exception is thrown
1112    beq     common_exceptionThrown      @ has exception
1113    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1115    GOTO_OPCODE(ip)                     @ jump to next instruction
1116
1117/* ------------------------------ */
1118    .balign 64
1119.L_OP_THROW: /* 0x27 */
1120/* File: armv5te/OP_THROW.S */
1121    /*
1122     * Throw an exception object in the current thread.
1123     */
1124    /* throw vAA */
1125    mov     r2, rINST, lsr #8           @ r2<- AA
1126    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1127    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1128    cmp     r1, #0                      @ null object?
1129    beq     common_errNullObject        @ yes, throw an NPE instead
1130    @ bypass dvmSetException, just store it
1131    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1132    b       common_exceptionThrown
1133
1134
1135/* ------------------------------ */
1136    .balign 64
1137.L_OP_GOTO: /* 0x28 */
1138/* File: armv5te/OP_GOTO.S */
1139    /*
1140     * Unconditional branch, 8-bit offset.
1141     *
1142     * The branch distance is a signed code-unit offset, which we need to
1143     * double to get a byte offset.
1144     */
1145    /* goto +AA */
1146    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1147    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1148    mov     r9, r9, lsl #1              @ r9<- byte offset
1149    bmi     common_backwardBranch       @ backward branch, do periodic checks
1150#if defined(WITH_JIT)
1151    GET_JIT_PROF_TABLE(r0)
1152    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1153    cmp     r0,#0
1154    bne     common_updateProfile
1155    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1156    GOTO_OPCODE(ip)                     @ jump to next instruction
1157#else
1158    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1159    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1160    GOTO_OPCODE(ip)                     @ jump to next instruction
1161#endif
1162
1163/* ------------------------------ */
1164    .balign 64
1165.L_OP_GOTO_16: /* 0x29 */
1166/* File: armv5te/OP_GOTO_16.S */
1167    /*
1168     * Unconditional branch, 16-bit offset.
1169     *
1170     * The branch distance is a signed code-unit offset, which we need to
1171     * double to get a byte offset.
1172     */
1173    /* goto/16 +AAAA */
1174    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1175    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1176    bmi     common_backwardBranch       @ backward branch, do periodic checks
1177#if defined(WITH_JIT)
1178    GET_JIT_PROF_TABLE(r0)
1179    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1180    cmp     r0,#0
1181    bne     common_updateProfile
1182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1183    GOTO_OPCODE(ip)                     @ jump to next instruction
1184#else
1185    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1186    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1187    GOTO_OPCODE(ip)                     @ jump to next instruction
1188#endif
1189
1190
1191/* ------------------------------ */
1192    .balign 64
1193.L_OP_GOTO_32: /* 0x2a */
1194/* File: armv5te/OP_GOTO_32.S */
1195    /*
1196     * Unconditional branch, 32-bit offset.
1197     *
1198     * The branch distance is a signed code-unit offset, which we need to
1199     * double to get a byte offset.
1200     *
1201     * Unlike most opcodes, this one is allowed to branch to itself, so
1202     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1203     * instruction doesn't affect the V flag, so we need to clear it
1204     * explicitly.
1205     */
1206    /* goto/32 +AAAAAAAA */
1207    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1208    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1209    cmp     ip, ip                      @ (clear V flag during stall)
1210    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1211    mov     r9, r0, asl #1              @ r9<- byte offset
1212    ble     common_backwardBranch       @ backward branch, do periodic checks
1213#if defined(WITH_JIT)
1214    GET_JIT_PROF_TABLE(r0)
1215    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1216    cmp     r0,#0
1217    bne     common_updateProfile
1218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1219    GOTO_OPCODE(ip)                     @ jump to next instruction
1220#else
1221    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1223    GOTO_OPCODE(ip)                     @ jump to next instruction
1224#endif
1225
1226/* ------------------------------ */
1227    .balign 64
1228.L_OP_PACKED_SWITCH: /* 0x2b */
1229/* File: armv5te/OP_PACKED_SWITCH.S */
1230    /*
1231     * Handle a packed-switch or sparse-switch instruction.  In both cases
1232     * we decode it and hand it off to a helper function.
1233     *
1234     * We don't really expect backward branches in a switch statement, but
1235     * they're perfectly legal, so we check for them here.
1236     *
1237     * for: packed-switch, sparse-switch
1238     */
1239    /* op vAA, +BBBB */
1240    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1241    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1242    mov     r3, rINST, lsr #8           @ r3<- AA
1243    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1244    GET_VREG(r1, r3)                    @ r1<- vAA
1245    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1246    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1247    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1248    bmi     common_backwardBranch       @ backward branch, do periodic checks
1249    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1250#if defined(WITH_JIT)
1251    GET_JIT_PROF_TABLE(r0)
1252    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1253    cmp     r0,#0
1254    bne     common_updateProfile
1255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1256    GOTO_OPCODE(ip)                     @ jump to next instruction
1257#else
1258    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1259    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1260    GOTO_OPCODE(ip)                     @ jump to next instruction
1261#endif
1262
1263
1264/* ------------------------------ */
1265    .balign 64
1266.L_OP_SPARSE_SWITCH: /* 0x2c */
1267/* File: armv5te/OP_SPARSE_SWITCH.S */
1268/* File: armv5te/OP_PACKED_SWITCH.S */
1269    /*
1270     * Handle a packed-switch or sparse-switch instruction.  In both cases
1271     * we decode it and hand it off to a helper function.
1272     *
1273     * We don't really expect backward branches in a switch statement, but
1274     * they're perfectly legal, so we check for them here.
1275     *
1276     * for: packed-switch, sparse-switch
1277     */
1278    /* op vAA, +BBBB */
1279    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1280    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1281    mov     r3, rINST, lsr #8           @ r3<- AA
1282    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1283    GET_VREG(r1, r3)                    @ r1<- vAA
1284    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1285    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1286    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1287    bmi     common_backwardBranch       @ backward branch, do periodic checks
1288    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1289#if defined(WITH_JIT)
1290    GET_JIT_PROF_TABLE(r0)
1291    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1292    cmp     r0,#0
1293    bne     common_updateProfile
1294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1295    GOTO_OPCODE(ip)                     @ jump to next instruction
1296#else
1297    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1298    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1299    GOTO_OPCODE(ip)                     @ jump to next instruction
1300#endif
1301
1302
1303
1304/* ------------------------------ */
1305    .balign 64
1306.L_OP_CMPL_FLOAT: /* 0x2d */
1307/* File: arm-vfp/OP_CMPL_FLOAT.S */
1308    /*
1309     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1310     * destination register based on the results of the comparison.
1311     *
1312     * int compare(x, y) {
1313     *     if (x == y) {
1314     *         return 0;
1315     *     } else if (x > y) {
1316     *         return 1;
1317     *     } else if (x < y) {
1318     *         return -1;
1319     *     } else {
1320     *         return -1;
1321     *     }
1322     * }
1323     */
1324    /* op vAA, vBB, vCC */
1325    FETCH(r0, 1)                        @ r0<- CCBB
1326    mov     r9, rINST, lsr #8           @ r9<- AA
1327    and     r2, r0, #255                @ r2<- BB
1328    mov     r3, r0, lsr #8              @ r3<- CC
1329    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1330    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1331    flds    s0, [r2]                    @ s0<- vBB
1332    flds    s1, [r3]                    @ s1<- vCC
1333    fcmpes  s0, s1                      @ compare (vBB, vCC)
1334    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1335    mvn     r0, #0                      @ r0<- -1 (default)
1336    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1337    fmstat                              @ export status flags
1338    movgt   r0, #1                      @ (greater than) r1<- 1
1339    moveq   r0, #0                      @ (equal) r1<- 0
1340    b       .LOP_CMPL_FLOAT_finish          @ argh
1341
1342
1343/* ------------------------------ */
1344    .balign 64
1345.L_OP_CMPG_FLOAT: /* 0x2e */
1346/* File: arm-vfp/OP_CMPG_FLOAT.S */
1347    /*
1348     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1349     * destination register based on the results of the comparison.
1350     *
1351     * int compare(x, y) {
1352     *     if (x == y) {
1353     *         return 0;
1354     *     } else if (x < y) {
1355     *         return -1;
1356     *     } else if (x > y) {
1357     *         return 1;
1358     *     } else {
1359     *         return 1;
1360     *     }
1361     * }
1362     */
1363    /* op vAA, vBB, vCC */
1364    FETCH(r0, 1)                        @ r0<- CCBB
1365    mov     r9, rINST, lsr #8           @ r9<- AA
1366    and     r2, r0, #255                @ r2<- BB
1367    mov     r3, r0, lsr #8              @ r3<- CC
1368    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1369    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1370    flds    s0, [r2]                    @ s0<- vBB
1371    flds    s1, [r3]                    @ s1<- vCC
1372    fcmpes  s0, s1                      @ compare (vBB, vCC)
1373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1374    mov     r0, #1                      @ r0<- 1 (default)
1375    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1376    fmstat                              @ export status flags
1377    mvnmi   r0, #0                      @ (less than) r1<- -1
1378    moveq   r0, #0                      @ (equal) r1<- 0
1379    b       .LOP_CMPG_FLOAT_finish          @ argh
1380
1381
1382/* ------------------------------ */
1383    .balign 64
1384.L_OP_CMPL_DOUBLE: /* 0x2f */
1385/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1386    /*
1387     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1388     * destination register based on the results of the comparison.
1389     *
1390     * int compare(x, y) {
1391     *     if (x == y) {
1392     *         return 0;
1393     *     } else if (x > y) {
1394     *         return 1;
1395     *     } else if (x < y) {
1396     *         return -1;
1397     *     } else {
1398     *         return -1;
1399     *     }
1400     * }
1401     */
1402    /* op vAA, vBB, vCC */
1403    FETCH(r0, 1)                        @ r0<- CCBB
1404    mov     r9, rINST, lsr #8           @ r9<- AA
1405    and     r2, r0, #255                @ r2<- BB
1406    mov     r3, r0, lsr #8              @ r3<- CC
1407    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1408    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1409    fldd    d0, [r2]                    @ d0<- vBB
1410    fldd    d1, [r3]                    @ d1<- vCC
1411    fcmped  d0, d1                      @ compare (vBB, vCC)
1412    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1413    mvn     r0, #0                      @ r0<- -1 (default)
1414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1415    fmstat                              @ export status flags
1416    movgt   r0, #1                      @ (greater than) r1<- 1
1417    moveq   r0, #0                      @ (equal) r1<- 0
1418    b       .LOP_CMPL_DOUBLE_finish          @ argh
1419
1420
1421/* ------------------------------ */
1422    .balign 64
1423.L_OP_CMPG_DOUBLE: /* 0x30 */
1424/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1425    /*
1426     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1427     * destination register based on the results of the comparison.
1428     *
1429     * int compare(x, y) {
1430     *     if (x == y) {
1431     *         return 0;
1432     *     } else if (x < y) {
1433     *         return -1;
1434     *     } else if (x > y) {
1435     *         return 1;
1436     *     } else {
1437     *         return 1;
1438     *     }
1439     * }
1440     */
1441    /* op vAA, vBB, vCC */
1442    FETCH(r0, 1)                        @ r0<- CCBB
1443    mov     r9, rINST, lsr #8           @ r9<- AA
1444    and     r2, r0, #255                @ r2<- BB
1445    mov     r3, r0, lsr #8              @ r3<- CC
1446    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1447    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1448    fldd    d0, [r2]                    @ d0<- vBB
1449    fldd    d1, [r3]                    @ d1<- vCC
1450    fcmped  d0, d1                      @ compare (vBB, vCC)
1451    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1452    mov     r0, #1                      @ r0<- 1 (default)
1453    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1454    fmstat                              @ export status flags
1455    mvnmi   r0, #0                      @ (less than) r1<- -1
1456    moveq   r0, #0                      @ (equal) r1<- 0
1457    b       .LOP_CMPG_DOUBLE_finish          @ argh
1458
1459
1460/* ------------------------------ */
1461    .balign 64
1462.L_OP_CMP_LONG: /* 0x31 */
1463/* File: armv5te/OP_CMP_LONG.S */
1464    /*
1465     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1466     * register based on the results of the comparison.
1467     *
1468     * We load the full values with LDM, but in practice many values could
1469     * be resolved by only looking at the high word.  This could be made
1470     * faster or slower by splitting the LDM into a pair of LDRs.
1471     *
1472     * If we just wanted to set condition flags, we could do this:
1473     *  subs    ip, r0, r2
1474     *  sbcs    ip, r1, r3
1475     *  subeqs  ip, r0, r2
1476     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1477     * integer value, which we can do with 2 conditional mov/mvn instructions
1478     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1479     * us a constant 5-cycle path plus a branch at the end to the
1480     * instruction epilogue code.  The multi-compare approach below needs
1481     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1482     * in the worst case (the 64-bit values are equal).
1483     */
1484    /* cmp-long vAA, vBB, vCC */
1485    FETCH(r0, 1)                        @ r0<- CCBB
1486    mov     r9, rINST, lsr #8           @ r9<- AA
1487    and     r2, r0, #255                @ r2<- BB
1488    mov     r3, r0, lsr #8              @ r3<- CC
1489    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1490    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1491    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1492    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1493    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1494    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1495    bgt     .LOP_CMP_LONG_greater
1496    subs    r1, r0, r2                  @ r1<- r0 - r2
1497    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1498    bne     .LOP_CMP_LONG_less
1499    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1500
1501/* ------------------------------ */
1502    .balign 64
1503.L_OP_IF_EQ: /* 0x32 */
1504/* File: armv6t2/OP_IF_EQ.S */
1505/* File: armv6t2/bincmp.S */
1506    /*
1507     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1508     * fragment that specifies the *reverse* comparison to perform, e.g.
1509     * for "if-le" you would use "gt".
1510     *
1511     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1512     */
1513    /* if-cmp vA, vB, +CCCC */
1514    mov     r1, rINST, lsr #12          @ r1<- B
1515    ubfx    r0, rINST, #8, #4           @ r0<- A
1516    GET_VREG(r3, r1)                    @ r3<- vB
1517    GET_VREG(r2, r0)                    @ r2<- vA
1518    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1519    cmp     r2, r3                      @ compare (vA, vB)
1520    bne  1f                      @ branch to 1 if comparison failed
1521    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1522    movs    r9, r9, asl #1              @ convert to bytes, check sign
1523    bmi     common_backwardBranch       @ yes, do periodic checks
15241:
1525#if defined(WITH_JIT)
1526    GET_JIT_PROF_TABLE(r0)
1527    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1528    b        common_testUpdateProfile
1529#else
1530    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1532    GOTO_OPCODE(ip)                     @ jump to next instruction
1533#endif
1534
1535
1536
1537/* ------------------------------ */
1538    .balign 64
1539.L_OP_IF_NE: /* 0x33 */
1540/* File: armv6t2/OP_IF_NE.S */
1541/* File: armv6t2/bincmp.S */
1542    /*
1543     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1544     * fragment that specifies the *reverse* comparison to perform, e.g.
1545     * for "if-le" you would use "gt".
1546     *
1547     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1548     */
1549    /* if-cmp vA, vB, +CCCC */
1550    mov     r1, rINST, lsr #12          @ r1<- B
1551    ubfx    r0, rINST, #8, #4           @ r0<- A
1552    GET_VREG(r3, r1)                    @ r3<- vB
1553    GET_VREG(r2, r0)                    @ r2<- vA
1554    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1555    cmp     r2, r3                      @ compare (vA, vB)
1556    beq  1f                      @ branch to 1 if comparison failed
1557    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1558    movs    r9, r9, asl #1              @ convert to bytes, check sign
1559    bmi     common_backwardBranch       @ yes, do periodic checks
15601:
1561#if defined(WITH_JIT)
1562    GET_JIT_PROF_TABLE(r0)
1563    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1564    b        common_testUpdateProfile
1565#else
1566    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1568    GOTO_OPCODE(ip)                     @ jump to next instruction
1569#endif
1570
1571
1572
1573/* ------------------------------ */
1574    .balign 64
1575.L_OP_IF_LT: /* 0x34 */
1576/* File: armv6t2/OP_IF_LT.S */
1577/* File: armv6t2/bincmp.S */
1578    /*
1579     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1580     * fragment that specifies the *reverse* comparison to perform, e.g.
1581     * for "if-le" you would use "gt".
1582     *
1583     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1584     */
1585    /* if-cmp vA, vB, +CCCC */
1586    mov     r1, rINST, lsr #12          @ r1<- B
1587    ubfx    r0, rINST, #8, #4           @ r0<- A
1588    GET_VREG(r3, r1)                    @ r3<- vB
1589    GET_VREG(r2, r0)                    @ r2<- vA
1590    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1591    cmp     r2, r3                      @ compare (vA, vB)
1592    bge  1f                      @ branch to 1 if comparison failed
1593    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1594    movs    r9, r9, asl #1              @ convert to bytes, check sign
1595    bmi     common_backwardBranch       @ yes, do periodic checks
15961:
1597#if defined(WITH_JIT)
1598    GET_JIT_PROF_TABLE(r0)
1599    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1600    b        common_testUpdateProfile
1601#else
1602    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1603    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1604    GOTO_OPCODE(ip)                     @ jump to next instruction
1605#endif
1606
1607
1608
1609/* ------------------------------ */
1610    .balign 64
1611.L_OP_IF_GE: /* 0x35 */
1612/* File: armv6t2/OP_IF_GE.S */
1613/* File: armv6t2/bincmp.S */
1614    /*
1615     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1616     * fragment that specifies the *reverse* comparison to perform, e.g.
1617     * for "if-le" you would use "gt".
1618     *
1619     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1620     */
1621    /* if-cmp vA, vB, +CCCC */
1622    mov     r1, rINST, lsr #12          @ r1<- B
1623    ubfx    r0, rINST, #8, #4           @ r0<- A
1624    GET_VREG(r3, r1)                    @ r3<- vB
1625    GET_VREG(r2, r0)                    @ r2<- vA
1626    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1627    cmp     r2, r3                      @ compare (vA, vB)
1628    blt  1f                      @ branch to 1 if comparison failed
1629    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1630    movs    r9, r9, asl #1              @ convert to bytes, check sign
1631    bmi     common_backwardBranch       @ yes, do periodic checks
16321:
1633#if defined(WITH_JIT)
1634    GET_JIT_PROF_TABLE(r0)
1635    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1636    b        common_testUpdateProfile
1637#else
1638    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1639    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1640    GOTO_OPCODE(ip)                     @ jump to next instruction
1641#endif
1642
1643
1644
1645/* ------------------------------ */
1646    .balign 64
1647.L_OP_IF_GT: /* 0x36 */
1648/* File: armv6t2/OP_IF_GT.S */
1649/* File: armv6t2/bincmp.S */
1650    /*
1651     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1652     * fragment that specifies the *reverse* comparison to perform, e.g.
1653     * for "if-le" you would use "gt".
1654     *
1655     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1656     */
1657    /* if-cmp vA, vB, +CCCC */
1658    mov     r1, rINST, lsr #12          @ r1<- B
1659    ubfx    r0, rINST, #8, #4           @ r0<- A
1660    GET_VREG(r3, r1)                    @ r3<- vB
1661    GET_VREG(r2, r0)                    @ r2<- vA
1662    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1663    cmp     r2, r3                      @ compare (vA, vB)
1664    ble  1f                      @ branch to 1 if comparison failed
1665    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1666    movs    r9, r9, asl #1              @ convert to bytes, check sign
1667    bmi     common_backwardBranch       @ yes, do periodic checks
16681:
1669#if defined(WITH_JIT)
1670    GET_JIT_PROF_TABLE(r0)
1671    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1672    b        common_testUpdateProfile
1673#else
1674    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1675    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1676    GOTO_OPCODE(ip)                     @ jump to next instruction
1677#endif
1678
1679
1680
1681/* ------------------------------ */
1682    .balign 64
1683.L_OP_IF_LE: /* 0x37 */
1684/* File: armv6t2/OP_IF_LE.S */
1685/* File: armv6t2/bincmp.S */
1686    /*
1687     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1688     * fragment that specifies the *reverse* comparison to perform, e.g.
1689     * for "if-le" you would use "gt".
1690     *
1691     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1692     */
1693    /* if-cmp vA, vB, +CCCC */
1694    mov     r1, rINST, lsr #12          @ r1<- B
1695    ubfx    r0, rINST, #8, #4           @ r0<- A
1696    GET_VREG(r3, r1)                    @ r3<- vB
1697    GET_VREG(r2, r0)                    @ r2<- vA
1698    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1699    cmp     r2, r3                      @ compare (vA, vB)
1700    bgt  1f                      @ branch to 1 if comparison failed
1701    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1702    movs    r9, r9, asl #1              @ convert to bytes, check sign
1703    bmi     common_backwardBranch       @ yes, do periodic checks
17041:
1705#if defined(WITH_JIT)
1706    GET_JIT_PROF_TABLE(r0)
1707    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1708    b        common_testUpdateProfile
1709#else
1710    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1712    GOTO_OPCODE(ip)                     @ jump to next instruction
1713#endif
1714
1715
1716
1717/* ------------------------------ */
1718    .balign 64
1719.L_OP_IF_EQZ: /* 0x38 */
1720/* File: armv5te/OP_IF_EQZ.S */
1721/* File: armv5te/zcmp.S */
1722    /*
1723     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1724     * fragment that specifies the *reverse* comparison to perform, e.g.
1725     * for "if-le" you would use "gt".
1726     *
1727     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1728     */
1729    /* if-cmp vAA, +BBBB */
1730    mov     r0, rINST, lsr #8           @ r0<- AA
1731    GET_VREG(r2, r0)                    @ r2<- vAA
1732    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1733    cmp     r2, #0                      @ compare (vA, 0)
1734    bne  1f                      @ branch to 1 if comparison failed
1735    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1736    movs    r9, r9, asl #1              @ convert to bytes, check sign
1737    bmi     common_backwardBranch       @ backward branch, do periodic checks
17381:
1739#if defined(WITH_JIT)
1740    GET_JIT_PROF_TABLE(r0)
1741    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1742    cmp     r0,#0
1743    bne     common_updateProfile
1744    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1745    GOTO_OPCODE(ip)                     @ jump to next instruction
1746#else
1747    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1749    GOTO_OPCODE(ip)                     @ jump to next instruction
1750#endif
1751
1752
1753
1754/* ------------------------------ */
1755    .balign 64
1756.L_OP_IF_NEZ: /* 0x39 */
1757/* File: armv5te/OP_IF_NEZ.S */
1758/* File: armv5te/zcmp.S */
1759    /*
1760     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1761     * fragment that specifies the *reverse* comparison to perform, e.g.
1762     * for "if-le" you would use "gt".
1763     *
1764     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1765     */
1766    /* if-cmp vAA, +BBBB */
1767    mov     r0, rINST, lsr #8           @ r0<- AA
1768    GET_VREG(r2, r0)                    @ r2<- vAA
1769    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1770    cmp     r2, #0                      @ compare (vA, 0)
1771    beq  1f                      @ branch to 1 if comparison failed
1772    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1773    movs    r9, r9, asl #1              @ convert to bytes, check sign
1774    bmi     common_backwardBranch       @ backward branch, do periodic checks
17751:
1776#if defined(WITH_JIT)
1777    GET_JIT_PROF_TABLE(r0)
1778    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1779    cmp     r0,#0
1780    bne     common_updateProfile
1781    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1782    GOTO_OPCODE(ip)                     @ jump to next instruction
1783#else
1784    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1785    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1786    GOTO_OPCODE(ip)                     @ jump to next instruction
1787#endif
1788
1789
1790
1791/* ------------------------------ */
1792    .balign 64
1793.L_OP_IF_LTZ: /* 0x3a */
1794/* File: armv5te/OP_IF_LTZ.S */
1795/* File: armv5te/zcmp.S */
1796    /*
1797     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1798     * fragment that specifies the *reverse* comparison to perform, e.g.
1799     * for "if-le" you would use "gt".
1800     *
1801     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1802     */
1803    /* if-cmp vAA, +BBBB */
1804    mov     r0, rINST, lsr #8           @ r0<- AA
1805    GET_VREG(r2, r0)                    @ r2<- vAA
1806    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1807    cmp     r2, #0                      @ compare (vA, 0)
1808    bge  1f                      @ branch to 1 if comparison failed
1809    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1810    movs    r9, r9, asl #1              @ convert to bytes, check sign
1811    bmi     common_backwardBranch       @ backward branch, do periodic checks
18121:
1813#if defined(WITH_JIT)
1814    GET_JIT_PROF_TABLE(r0)
1815    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1816    cmp     r0,#0
1817    bne     common_updateProfile
1818    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1819    GOTO_OPCODE(ip)                     @ jump to next instruction
1820#else
1821    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1823    GOTO_OPCODE(ip)                     @ jump to next instruction
1824#endif
1825
1826
1827
1828/* ------------------------------ */
1829    .balign 64
1830.L_OP_IF_GEZ: /* 0x3b */
1831/* File: armv5te/OP_IF_GEZ.S */
1832/* File: armv5te/zcmp.S */
1833    /*
1834     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1835     * fragment that specifies the *reverse* comparison to perform, e.g.
1836     * for "if-le" you would use "gt".
1837     *
1838     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1839     */
1840    /* if-cmp vAA, +BBBB */
1841    mov     r0, rINST, lsr #8           @ r0<- AA
1842    GET_VREG(r2, r0)                    @ r2<- vAA
1843    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1844    cmp     r2, #0                      @ compare (vA, 0)
1845    blt  1f                      @ branch to 1 if comparison failed
1846    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1847    movs    r9, r9, asl #1              @ convert to bytes, check sign
1848    bmi     common_backwardBranch       @ backward branch, do periodic checks
18491:
1850#if defined(WITH_JIT)
1851    GET_JIT_PROF_TABLE(r0)
1852    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1853    cmp     r0,#0
1854    bne     common_updateProfile
1855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1856    GOTO_OPCODE(ip)                     @ jump to next instruction
1857#else
1858    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1859    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1860    GOTO_OPCODE(ip)                     @ jump to next instruction
1861#endif
1862
1863
1864
1865/* ------------------------------ */
1866    .balign 64
1867.L_OP_IF_GTZ: /* 0x3c */
1868/* File: armv5te/OP_IF_GTZ.S */
1869/* File: armv5te/zcmp.S */
1870    /*
1871     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1872     * fragment that specifies the *reverse* comparison to perform, e.g.
1873     * for "if-le" you would use "gt".
1874     *
1875     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1876     */
1877    /* if-cmp vAA, +BBBB */
1878    mov     r0, rINST, lsr #8           @ r0<- AA
1879    GET_VREG(r2, r0)                    @ r2<- vAA
1880    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1881    cmp     r2, #0                      @ compare (vA, 0)
1882    ble  1f                      @ branch to 1 if comparison failed
1883    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1884    movs    r9, r9, asl #1              @ convert to bytes, check sign
1885    bmi     common_backwardBranch       @ backward branch, do periodic checks
18861:
1887#if defined(WITH_JIT)
1888    GET_JIT_PROF_TABLE(r0)
1889    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1890    cmp     r0,#0
1891    bne     common_updateProfile
1892    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1893    GOTO_OPCODE(ip)                     @ jump to next instruction
1894#else
1895    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1897    GOTO_OPCODE(ip)                     @ jump to next instruction
1898#endif
1899
1900
1901
1902/* ------------------------------ */
1903    .balign 64
1904.L_OP_IF_LEZ: /* 0x3d */
1905/* File: armv5te/OP_IF_LEZ.S */
1906/* File: armv5te/zcmp.S */
1907    /*
1908     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1909     * fragment that specifies the *reverse* comparison to perform, e.g.
1910     * for "if-le" you would use "gt".
1911     *
1912     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1913     */
1914    /* if-cmp vAA, +BBBB */
1915    mov     r0, rINST, lsr #8           @ r0<- AA
1916    GET_VREG(r2, r0)                    @ r2<- vAA
1917    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1918    cmp     r2, #0                      @ compare (vA, 0)
1919    bgt  1f                      @ branch to 1 if comparison failed
1920    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1921    movs    r9, r9, asl #1              @ convert to bytes, check sign
1922    bmi     common_backwardBranch       @ backward branch, do periodic checks
19231:
1924#if defined(WITH_JIT)
1925    GET_JIT_PROF_TABLE(r0)
1926    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1927    cmp     r0,#0
1928    bne     common_updateProfile
1929    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1930    GOTO_OPCODE(ip)                     @ jump to next instruction
1931#else
1932    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1934    GOTO_OPCODE(ip)                     @ jump to next instruction
1935#endif
1936
1937
1938
1939/* ------------------------------ */
1940    .balign 64
1941.L_OP_UNUSED_3E: /* 0x3e */
1942/* File: armv5te/OP_UNUSED_3E.S */
1943/* File: armv5te/unused.S */
1944    bl      common_abort
1945
1946
1947
1948/* ------------------------------ */
1949    .balign 64
1950.L_OP_UNUSED_3F: /* 0x3f */
1951/* File: armv5te/OP_UNUSED_3F.S */
1952/* File: armv5te/unused.S */
1953    bl      common_abort
1954
1955
1956
1957/* ------------------------------ */
1958    .balign 64
1959.L_OP_UNUSED_40: /* 0x40 */
1960/* File: armv5te/OP_UNUSED_40.S */
1961/* File: armv5te/unused.S */
1962    bl      common_abort
1963
1964
1965
1966/* ------------------------------ */
1967    .balign 64
1968.L_OP_UNUSED_41: /* 0x41 */
1969/* File: armv5te/OP_UNUSED_41.S */
1970/* File: armv5te/unused.S */
1971    bl      common_abort
1972
1973
1974
1975/* ------------------------------ */
1976    .balign 64
1977.L_OP_UNUSED_42: /* 0x42 */
1978/* File: armv5te/OP_UNUSED_42.S */
1979/* File: armv5te/unused.S */
1980    bl      common_abort
1981
1982
1983
1984/* ------------------------------ */
1985    .balign 64
1986.L_OP_UNUSED_43: /* 0x43 */
1987/* File: armv5te/OP_UNUSED_43.S */
1988/* File: armv5te/unused.S */
1989    bl      common_abort
1990
1991
1992
1993/* ------------------------------ */
1994    .balign 64
1995.L_OP_AGET: /* 0x44 */
1996/* File: armv5te/OP_AGET.S */
1997    /*
1998     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1999     *
2000     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2001     * instructions.  We use a pair of FETCH_Bs instead.
2002     *
2003     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2004     */
2005    /* op vAA, vBB, vCC */
2006    FETCH_B(r2, 1, 0)                   @ r2<- BB
2007    mov     r9, rINST, lsr #8           @ r9<- AA
2008    FETCH_B(r3, 1, 1)                   @ r3<- CC
2009    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2010    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2011    cmp     r0, #0                      @ null array object?
2012    beq     common_errNullObject        @ yes, bail
2013    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2014    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2015    cmp     r1, r3                      @ compare unsigned index, length
2016    bcs     common_errArrayIndex        @ index >= length, bail
2017    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2018    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2019    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2020    SET_VREG(r2, r9)                    @ vAA<- r2
2021    GOTO_OPCODE(ip)                     @ jump to next instruction
2022
2023
2024/* ------------------------------ */
2025    .balign 64
2026.L_OP_AGET_WIDE: /* 0x45 */
2027/* File: armv5te/OP_AGET_WIDE.S */
2028    /*
2029     * Array get, 64 bits.  vAA <- vBB[vCC].
2030     *
2031     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2032     */
2033    /* aget-wide vAA, vBB, vCC */
2034    FETCH(r0, 1)                        @ r0<- CCBB
2035    mov     r9, rINST, lsr #8           @ r9<- AA
2036    and     r2, r0, #255                @ r2<- BB
2037    mov     r3, r0, lsr #8              @ r3<- CC
2038    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2039    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2040    cmp     r0, #0                      @ null array object?
2041    beq     common_errNullObject        @ yes, bail
2042    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2043    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2044    cmp     r1, r3                      @ compare unsigned index, length
2045    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2046    b       common_errArrayIndex        @ index >= length, bail
2047    @ May want to swap the order of these two branches depending on how the
2048    @ branch prediction (if any) handles conditional forward branches vs.
2049    @ unconditional forward branches.
2050
2051/* ------------------------------ */
2052    .balign 64
2053.L_OP_AGET_OBJECT: /* 0x46 */
2054/* File: armv5te/OP_AGET_OBJECT.S */
2055/* File: armv5te/OP_AGET.S */
2056    /*
2057     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2058     *
2059     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2060     * instructions.  We use a pair of FETCH_Bs instead.
2061     *
2062     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2063     */
2064    /* op vAA, vBB, vCC */
2065    FETCH_B(r2, 1, 0)                   @ r2<- BB
2066    mov     r9, rINST, lsr #8           @ r9<- AA
2067    FETCH_B(r3, 1, 1)                   @ r3<- CC
2068    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2069    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2070    cmp     r0, #0                      @ null array object?
2071    beq     common_errNullObject        @ yes, bail
2072    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2073    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2074    cmp     r1, r3                      @ compare unsigned index, length
2075    bcs     common_errArrayIndex        @ index >= length, bail
2076    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2077    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2078    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2079    SET_VREG(r2, r9)                    @ vAA<- r2
2080    GOTO_OPCODE(ip)                     @ jump to next instruction
2081
2082
2083
2084/* ------------------------------ */
2085    .balign 64
2086.L_OP_AGET_BOOLEAN: /* 0x47 */
2087/* File: armv5te/OP_AGET_BOOLEAN.S */
2088/* File: armv5te/OP_AGET.S */
2089    /*
2090     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2091     *
2092     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2093     * instructions.  We use a pair of FETCH_Bs instead.
2094     *
2095     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2096     */
2097    /* op vAA, vBB, vCC */
2098    FETCH_B(r2, 1, 0)                   @ r2<- BB
2099    mov     r9, rINST, lsr #8           @ r9<- AA
2100    FETCH_B(r3, 1, 1)                   @ r3<- CC
2101    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2102    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2103    cmp     r0, #0                      @ null array object?
2104    beq     common_errNullObject        @ yes, bail
2105    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2106    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2107    cmp     r1, r3                      @ compare unsigned index, length
2108    bcs     common_errArrayIndex        @ index >= length, bail
2109    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2110    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2111    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2112    SET_VREG(r2, r9)                    @ vAA<- r2
2113    GOTO_OPCODE(ip)                     @ jump to next instruction
2114
2115
2116
2117/* ------------------------------ */
2118    .balign 64
2119.L_OP_AGET_BYTE: /* 0x48 */
2120/* File: armv5te/OP_AGET_BYTE.S */
2121/* File: armv5te/OP_AGET.S */
2122    /*
2123     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2124     *
2125     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2126     * instructions.  We use a pair of FETCH_Bs instead.
2127     *
2128     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2129     */
2130    /* op vAA, vBB, vCC */
2131    FETCH_B(r2, 1, 0)                   @ r2<- BB
2132    mov     r9, rINST, lsr #8           @ r9<- AA
2133    FETCH_B(r3, 1, 1)                   @ r3<- CC
2134    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2135    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2136    cmp     r0, #0                      @ null array object?
2137    beq     common_errNullObject        @ yes, bail
2138    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2139    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2140    cmp     r1, r3                      @ compare unsigned index, length
2141    bcs     common_errArrayIndex        @ index >= length, bail
2142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2143    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2145    SET_VREG(r2, r9)                    @ vAA<- r2
2146    GOTO_OPCODE(ip)                     @ jump to next instruction
2147
2148
2149
2150/* ------------------------------ */
2151    .balign 64
2152.L_OP_AGET_CHAR: /* 0x49 */
2153/* File: armv5te/OP_AGET_CHAR.S */
2154/* File: armv5te/OP_AGET.S */
2155    /*
2156     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2157     *
2158     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2159     * instructions.  We use a pair of FETCH_Bs instead.
2160     *
2161     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2162     */
2163    /* op vAA, vBB, vCC */
2164    FETCH_B(r2, 1, 0)                   @ r2<- BB
2165    mov     r9, rINST, lsr #8           @ r9<- AA
2166    FETCH_B(r3, 1, 1)                   @ r3<- CC
2167    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2168    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2169    cmp     r0, #0                      @ null array object?
2170    beq     common_errNullObject        @ yes, bail
2171    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2172    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2173    cmp     r1, r3                      @ compare unsigned index, length
2174    bcs     common_errArrayIndex        @ index >= length, bail
2175    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2176    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2177    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2178    SET_VREG(r2, r9)                    @ vAA<- r2
2179    GOTO_OPCODE(ip)                     @ jump to next instruction
2180
2181
2182
2183/* ------------------------------ */
2184    .balign 64
2185.L_OP_AGET_SHORT: /* 0x4a */
2186/* File: armv5te/OP_AGET_SHORT.S */
2187/* File: armv5te/OP_AGET.S */
2188    /*
2189     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2190     *
2191     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2192     * instructions.  We use a pair of FETCH_Bs instead.
2193     *
2194     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2195     */
2196    /* op vAA, vBB, vCC */
2197    FETCH_B(r2, 1, 0)                   @ r2<- BB
2198    mov     r9, rINST, lsr #8           @ r9<- AA
2199    FETCH_B(r3, 1, 1)                   @ r3<- CC
2200    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2201    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2202    cmp     r0, #0                      @ null array object?
2203    beq     common_errNullObject        @ yes, bail
2204    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2205    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2206    cmp     r1, r3                      @ compare unsigned index, length
2207    bcs     common_errArrayIndex        @ index >= length, bail
2208    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2209    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2210    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2211    SET_VREG(r2, r9)                    @ vAA<- r2
2212    GOTO_OPCODE(ip)                     @ jump to next instruction
2213
2214
2215
2216/* ------------------------------ */
2217    .balign 64
2218.L_OP_APUT: /* 0x4b */
2219/* File: armv5te/OP_APUT.S */
2220    /*
2221     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2222     *
2223     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2224     * instructions.  We use a pair of FETCH_Bs instead.
2225     *
2226     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2227     */
2228    /* op vAA, vBB, vCC */
2229    FETCH_B(r2, 1, 0)                   @ r2<- BB
2230    mov     r9, rINST, lsr #8           @ r9<- AA
2231    FETCH_B(r3, 1, 1)                   @ r3<- CC
2232    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2233    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2234    cmp     r0, #0                      @ null array object?
2235    beq     common_errNullObject        @ yes, bail
2236    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2237    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2238    cmp     r1, r3                      @ compare unsigned index, length
2239    bcs     common_errArrayIndex        @ index >= length, bail
2240    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2241    GET_VREG(r2, r9)                    @ r2<- vAA
2242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2243    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2244    GOTO_OPCODE(ip)                     @ jump to next instruction
2245
2246
2247/* ------------------------------ */
2248    .balign 64
2249.L_OP_APUT_WIDE: /* 0x4c */
2250/* File: armv5te/OP_APUT_WIDE.S */
2251    /*
2252     * Array put, 64 bits.  vBB[vCC] <- vAA.
2253     *
2254     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2255     */
2256    /* aput-wide vAA, vBB, vCC */
2257    FETCH(r0, 1)                        @ r0<- CCBB
2258    mov     r9, rINST, lsr #8           @ r9<- AA
2259    and     r2, r0, #255                @ r2<- BB
2260    mov     r3, r0, lsr #8              @ r3<- CC
2261    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2262    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2263    cmp     r0, #0                      @ null array object?
2264    beq     common_errNullObject        @ yes, bail
2265    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2266    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2267    cmp     r1, r3                      @ compare unsigned index, length
2268    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2269    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2270    b       common_errArrayIndex        @ index >= length, bail
2271    @ May want to swap the order of these two branches depending on how the
2272    @ branch prediction (if any) handles conditional forward branches vs.
2273    @ unconditional forward branches.
2274
2275/* ------------------------------ */
2276    .balign 64
2277.L_OP_APUT_OBJECT: /* 0x4d */
2278/* File: armv5te/OP_APUT_OBJECT.S */
2279    /*
2280     * Store an object into an array.  vBB[vCC] <- vAA.
2281     *
2282     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2283     * instructions.  We use a pair of FETCH_Bs instead.
2284     */
2285    /* op vAA, vBB, vCC */
2286    FETCH(r0, 1)                        @ r0<- CCBB
2287    mov     r9, rINST, lsr #8           @ r9<- AA
2288    and     r2, r0, #255                @ r2<- BB
2289    mov     r3, r0, lsr #8              @ r3<- CC
2290    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2291    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2292    cmp     r1, #0                      @ null array object?
2293    GET_VREG(r9, r9)                    @ r9<- vAA
2294    beq     common_errNullObject        @ yes, bail
2295    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2296    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2297    cmp     r0, r3                      @ compare unsigned index, length
2298    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2299    b       common_errArrayIndex        @ index >= length, bail
2300
2301
2302/* ------------------------------ */
2303    .balign 64
2304.L_OP_APUT_BOOLEAN: /* 0x4e */
2305/* File: armv5te/OP_APUT_BOOLEAN.S */
2306/* File: armv5te/OP_APUT.S */
2307    /*
2308     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2309     *
2310     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2311     * instructions.  We use a pair of FETCH_Bs instead.
2312     *
2313     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2314     */
2315    /* op vAA, vBB, vCC */
2316    FETCH_B(r2, 1, 0)                   @ r2<- BB
2317    mov     r9, rINST, lsr #8           @ r9<- AA
2318    FETCH_B(r3, 1, 1)                   @ r3<- CC
2319    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2320    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2321    cmp     r0, #0                      @ null array object?
2322    beq     common_errNullObject        @ yes, bail
2323    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2324    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2325    cmp     r1, r3                      @ compare unsigned index, length
2326    bcs     common_errArrayIndex        @ index >= length, bail
2327    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2328    GET_VREG(r2, r9)                    @ r2<- vAA
2329    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2330    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2331    GOTO_OPCODE(ip)                     @ jump to next instruction
2332
2333
2334
2335/* ------------------------------ */
2336    .balign 64
2337.L_OP_APUT_BYTE: /* 0x4f */
2338/* File: armv5te/OP_APUT_BYTE.S */
2339/* File: armv5te/OP_APUT.S */
2340    /*
2341     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2342     *
2343     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2344     * instructions.  We use a pair of FETCH_Bs instead.
2345     *
2346     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2347     */
2348    /* op vAA, vBB, vCC */
2349    FETCH_B(r2, 1, 0)                   @ r2<- BB
2350    mov     r9, rINST, lsr #8           @ r9<- AA
2351    FETCH_B(r3, 1, 1)                   @ r3<- CC
2352    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2353    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2354    cmp     r0, #0                      @ null array object?
2355    beq     common_errNullObject        @ yes, bail
2356    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2357    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2358    cmp     r1, r3                      @ compare unsigned index, length
2359    bcs     common_errArrayIndex        @ index >= length, bail
2360    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2361    GET_VREG(r2, r9)                    @ r2<- vAA
2362    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2363    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2364    GOTO_OPCODE(ip)                     @ jump to next instruction
2365
2366
2367
2368/* ------------------------------ */
2369    .balign 64
2370.L_OP_APUT_CHAR: /* 0x50 */
2371/* File: armv5te/OP_APUT_CHAR.S */
2372/* File: armv5te/OP_APUT.S */
2373    /*
2374     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2375     *
2376     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2377     * instructions.  We use a pair of FETCH_Bs instead.
2378     *
2379     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2380     */
2381    /* op vAA, vBB, vCC */
2382    FETCH_B(r2, 1, 0)                   @ r2<- BB
2383    mov     r9, rINST, lsr #8           @ r9<- AA
2384    FETCH_B(r3, 1, 1)                   @ r3<- CC
2385    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2386    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2387    cmp     r0, #0                      @ null array object?
2388    beq     common_errNullObject        @ yes, bail
2389    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2390    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2391    cmp     r1, r3                      @ compare unsigned index, length
2392    bcs     common_errArrayIndex        @ index >= length, bail
2393    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2394    GET_VREG(r2, r9)                    @ r2<- vAA
2395    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2396    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2397    GOTO_OPCODE(ip)                     @ jump to next instruction
2398
2399
2400
2401/* ------------------------------ */
2402    .balign 64
2403.L_OP_APUT_SHORT: /* 0x51 */
2404/* File: armv5te/OP_APUT_SHORT.S */
2405/* File: armv5te/OP_APUT.S */
2406    /*
2407     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2408     *
2409     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2410     * instructions.  We use a pair of FETCH_Bs instead.
2411     *
2412     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2413     */
2414    /* op vAA, vBB, vCC */
2415    FETCH_B(r2, 1, 0)                   @ r2<- BB
2416    mov     r9, rINST, lsr #8           @ r9<- AA
2417    FETCH_B(r3, 1, 1)                   @ r3<- CC
2418    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2419    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2420    cmp     r0, #0                      @ null array object?
2421    beq     common_errNullObject        @ yes, bail
2422    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2423    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2424    cmp     r1, r3                      @ compare unsigned index, length
2425    bcs     common_errArrayIndex        @ index >= length, bail
2426    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2427    GET_VREG(r2, r9)                    @ r2<- vAA
2428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2429    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2430    GOTO_OPCODE(ip)                     @ jump to next instruction
2431
2432
2433
2434/* ------------------------------ */
2435    .balign 64
2436.L_OP_IGET: /* 0x52 */
2437/* File: armv6t2/OP_IGET.S */
2438    /*
2439     * General 32-bit instance field get.
2440     *
2441     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2442     */
2443    /* op vA, vB, field@CCCC */
2444    mov     r0, rINST, lsr #12          @ r0<- B
2445    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2446    FETCH(r1, 1)                        @ r1<- field ref CCCC
2447    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2448    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2449    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2450    cmp     r0, #0                      @ is resolved entry null?
2451    bne     .LOP_IGET_finish          @ no, already resolved
24528:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2453    EXPORT_PC()                         @ resolve() could throw
2454    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2455    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2456    cmp     r0, #0
2457    bne     .LOP_IGET_finish
2458    b       common_exceptionThrown
2459
2460/* ------------------------------ */
2461    .balign 64
2462.L_OP_IGET_WIDE: /* 0x53 */
2463/* File: armv6t2/OP_IGET_WIDE.S */
2464    /*
2465     * Wide 32-bit instance field get.
2466     */
2467    /* iget-wide vA, vB, field@CCCC */
2468    mov     r0, rINST, lsr #12          @ r0<- B
2469    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2470    FETCH(r1, 1)                        @ r1<- field ref CCCC
2471    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2472    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2473    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2474    cmp     r0, #0                      @ is resolved entry null?
2475    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24768:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2477    EXPORT_PC()                         @ resolve() could throw
2478    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2479    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2480    cmp     r0, #0
2481    bne     .LOP_IGET_WIDE_finish
2482    b       common_exceptionThrown
2483
2484/* ------------------------------ */
2485    .balign 64
2486.L_OP_IGET_OBJECT: /* 0x54 */
2487/* File: armv5te/OP_IGET_OBJECT.S */
2488/* File: armv5te/OP_IGET.S */
2489    /*
2490     * General 32-bit instance field get.
2491     *
2492     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2493     */
2494    /* op vA, vB, field@CCCC */
2495    mov     r0, rINST, lsr #12          @ r0<- B
2496    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2497    FETCH(r1, 1)                        @ r1<- field ref CCCC
2498    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2499    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2500    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2501    cmp     r0, #0                      @ is resolved entry null?
2502    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25038:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2504    EXPORT_PC()                         @ resolve() could throw
2505    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2506    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2507    cmp     r0, #0
2508    bne     .LOP_IGET_OBJECT_finish
2509    b       common_exceptionThrown
2510
2511
2512/* ------------------------------ */
2513    .balign 64
2514.L_OP_IGET_BOOLEAN: /* 0x55 */
2515/* File: armv5te/OP_IGET_BOOLEAN.S */
2516@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2517/* File: armv5te/OP_IGET.S */
2518    /*
2519     * General 32-bit instance field get.
2520     *
2521     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2522     */
2523    /* op vA, vB, field@CCCC */
2524    mov     r0, rINST, lsr #12          @ r0<- B
2525    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2526    FETCH(r1, 1)                        @ r1<- field ref CCCC
2527    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2528    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2529    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2530    cmp     r0, #0                      @ is resolved entry null?
2531    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25328:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2533    EXPORT_PC()                         @ resolve() could throw
2534    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2535    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2536    cmp     r0, #0
2537    bne     .LOP_IGET_BOOLEAN_finish
2538    b       common_exceptionThrown
2539
2540
2541/* ------------------------------ */
2542    .balign 64
2543.L_OP_IGET_BYTE: /* 0x56 */
2544/* File: armv5te/OP_IGET_BYTE.S */
2545@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2546/* File: armv5te/OP_IGET.S */
2547    /*
2548     * General 32-bit instance field get.
2549     *
2550     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2551     */
2552    /* op vA, vB, field@CCCC */
2553    mov     r0, rINST, lsr #12          @ r0<- B
2554    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2555    FETCH(r1, 1)                        @ r1<- field ref CCCC
2556    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2557    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2558    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2559    cmp     r0, #0                      @ is resolved entry null?
2560    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25618:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2562    EXPORT_PC()                         @ resolve() could throw
2563    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2564    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2565    cmp     r0, #0
2566    bne     .LOP_IGET_BYTE_finish
2567    b       common_exceptionThrown
2568
2569
2570/* ------------------------------ */
2571    .balign 64
2572.L_OP_IGET_CHAR: /* 0x57 */
2573/* File: armv5te/OP_IGET_CHAR.S */
2574@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2575/* File: armv5te/OP_IGET.S */
2576    /*
2577     * General 32-bit instance field get.
2578     *
2579     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2580     */
2581    /* op vA, vB, field@CCCC */
2582    mov     r0, rINST, lsr #12          @ r0<- B
2583    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2584    FETCH(r1, 1)                        @ r1<- field ref CCCC
2585    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2586    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2587    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2588    cmp     r0, #0                      @ is resolved entry null?
2589    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25908:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2591    EXPORT_PC()                         @ resolve() could throw
2592    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2593    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2594    cmp     r0, #0
2595    bne     .LOP_IGET_CHAR_finish
2596    b       common_exceptionThrown
2597
2598
2599/* ------------------------------ */
2600    .balign 64
2601.L_OP_IGET_SHORT: /* 0x58 */
2602/* File: armv5te/OP_IGET_SHORT.S */
2603@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2604/* File: armv5te/OP_IGET.S */
2605    /*
2606     * General 32-bit instance field get.
2607     *
2608     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2609     */
2610    /* op vA, vB, field@CCCC */
2611    mov     r0, rINST, lsr #12          @ r0<- B
2612    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2613    FETCH(r1, 1)                        @ r1<- field ref CCCC
2614    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2615    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2616    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2617    cmp     r0, #0                      @ is resolved entry null?
2618    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26198:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2620    EXPORT_PC()                         @ resolve() could throw
2621    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2622    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2623    cmp     r0, #0
2624    bne     .LOP_IGET_SHORT_finish
2625    b       common_exceptionThrown
2626
2627
2628/* ------------------------------ */
2629    .balign 64
2630.L_OP_IPUT: /* 0x59 */
2631/* File: armv6t2/OP_IPUT.S */
2632    /*
2633     * General 32-bit instance field put.
2634     *
2635     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2636     */
2637    /* op vA, vB, field@CCCC */
2638    mov     r0, rINST, lsr #12          @ r0<- B
2639    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2640    FETCH(r1, 1)                        @ r1<- field ref CCCC
2641    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2642    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2643    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2644    cmp     r0, #0                      @ is resolved entry null?
2645    bne     .LOP_IPUT_finish          @ no, already resolved
26468:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2647    EXPORT_PC()                         @ resolve() could throw
2648    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2649    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2650    cmp     r0, #0                      @ success?
2651    bne     .LOP_IPUT_finish          @ yes, finish up
2652    b       common_exceptionThrown
2653
2654/* ------------------------------ */
2655    .balign 64
2656.L_OP_IPUT_WIDE: /* 0x5a */
2657/* File: armv6t2/OP_IPUT_WIDE.S */
2658    /* iput-wide vA, vB, field@CCCC */
2659    mov     r0, rINST, lsr #12          @ r0<- B
2660    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2661    FETCH(r1, 1)                        @ r1<- field ref CCCC
2662    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2663    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2664    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2665    cmp     r0, #0                      @ is resolved entry null?
2666    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26678:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2668    EXPORT_PC()                         @ resolve() could throw
2669    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2670    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2671    cmp     r0, #0                      @ success?
2672    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2673    b       common_exceptionThrown
2674
2675/* ------------------------------ */
2676    .balign 64
2677.L_OP_IPUT_OBJECT: /* 0x5b */
2678/* File: armv5te/OP_IPUT_OBJECT.S */
2679/* File: armv5te/OP_IPUT.S */
2680    /*
2681     * General 32-bit instance field put.
2682     *
2683     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2684     */
2685    /* op vA, vB, field@CCCC */
2686    mov     r0, rINST, lsr #12          @ r0<- B
2687    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2688    FETCH(r1, 1)                        @ r1<- field ref CCCC
2689    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2690    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2691    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2692    cmp     r0, #0                      @ is resolved entry null?
2693    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2695    EXPORT_PC()                         @ resolve() could throw
2696    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2697    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2698    cmp     r0, #0                      @ success?
2699    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2700    b       common_exceptionThrown
2701
2702
2703/* ------------------------------ */
2704    .balign 64
2705.L_OP_IPUT_BOOLEAN: /* 0x5c */
2706/* File: armv5te/OP_IPUT_BOOLEAN.S */
2707@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2708/* File: armv5te/OP_IPUT.S */
2709    /*
2710     * General 32-bit instance field put.
2711     *
2712     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2713     */
2714    /* op vA, vB, field@CCCC */
2715    mov     r0, rINST, lsr #12          @ r0<- B
2716    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2717    FETCH(r1, 1)                        @ r1<- field ref CCCC
2718    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2719    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2720    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2721    cmp     r0, #0                      @ is resolved entry null?
2722    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27238:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2724    EXPORT_PC()                         @ resolve() could throw
2725    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2726    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2727    cmp     r0, #0                      @ success?
2728    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2729    b       common_exceptionThrown
2730
2731
2732/* ------------------------------ */
2733    .balign 64
2734.L_OP_IPUT_BYTE: /* 0x5d */
2735/* File: armv5te/OP_IPUT_BYTE.S */
2736@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2737/* File: armv5te/OP_IPUT.S */
2738    /*
2739     * General 32-bit instance field put.
2740     *
2741     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2742     */
2743    /* op vA, vB, field@CCCC */
2744    mov     r0, rINST, lsr #12          @ r0<- B
2745    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2746    FETCH(r1, 1)                        @ r1<- field ref CCCC
2747    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2748    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2749    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2750    cmp     r0, #0                      @ is resolved entry null?
2751    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27528:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2753    EXPORT_PC()                         @ resolve() could throw
2754    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2755    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2756    cmp     r0, #0                      @ success?
2757    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2758    b       common_exceptionThrown
2759
2760
2761/* ------------------------------ */
2762    .balign 64
2763.L_OP_IPUT_CHAR: /* 0x5e */
2764/* File: armv5te/OP_IPUT_CHAR.S */
2765@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2766/* File: armv5te/OP_IPUT.S */
2767    /*
2768     * General 32-bit instance field put.
2769     *
2770     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2771     */
2772    /* op vA, vB, field@CCCC */
2773    mov     r0, rINST, lsr #12          @ r0<- B
2774    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2775    FETCH(r1, 1)                        @ r1<- field ref CCCC
2776    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2777    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2778    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2779    cmp     r0, #0                      @ is resolved entry null?
2780    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27818:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2782    EXPORT_PC()                         @ resolve() could throw
2783    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2784    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2785    cmp     r0, #0                      @ success?
2786    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2787    b       common_exceptionThrown
2788
2789
2790/* ------------------------------ */
2791    .balign 64
2792.L_OP_IPUT_SHORT: /* 0x5f */
2793/* File: armv5te/OP_IPUT_SHORT.S */
2794@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2795/* File: armv5te/OP_IPUT.S */
2796    /*
2797     * General 32-bit instance field put.
2798     *
2799     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2800     */
2801    /* op vA, vB, field@CCCC */
2802    mov     r0, rINST, lsr #12          @ r0<- B
2803    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2804    FETCH(r1, 1)                        @ r1<- field ref CCCC
2805    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2806    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2807    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2808    cmp     r0, #0                      @ is resolved entry null?
2809    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28108:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2811    EXPORT_PC()                         @ resolve() could throw
2812    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2813    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2814    cmp     r0, #0                      @ success?
2815    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2816    b       common_exceptionThrown
2817
2818
2819/* ------------------------------ */
2820    .balign 64
2821.L_OP_SGET: /* 0x60 */
2822/* File: armv5te/OP_SGET.S */
2823    /*
2824     * General 32-bit SGET handler.
2825     *
2826     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2827     */
2828    /* op vAA, field@BBBB */
2829    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2830    FETCH(r1, 1)                        @ r1<- field ref BBBB
2831    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2832    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2833    cmp     r0, #0                      @ is resolved entry null?
2834    beq     .LOP_SGET_resolve         @ yes, do resolve
2835.LOP_SGET_finish: @ field ptr in r0
2836    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2837    mov     r2, rINST, lsr #8           @ r2<- AA
2838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2839    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2841    GOTO_OPCODE(ip)                     @ jump to next instruction
2842
2843/* ------------------------------ */
2844    .balign 64
2845.L_OP_SGET_WIDE: /* 0x61 */
2846/* File: armv5te/OP_SGET_WIDE.S */
2847    /*
2848     * 64-bit SGET handler.
2849     */
2850    /* sget-wide vAA, field@BBBB */
2851    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2852    FETCH(r1, 1)                        @ r1<- field ref BBBB
2853    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2854    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2855    cmp     r0, #0                      @ is resolved entry null?
2856    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2857.LOP_SGET_WIDE_finish:
2858    mov     r1, rINST, lsr #8           @ r1<- AA
2859    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2860    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2861    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2862    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2863    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2864    GOTO_OPCODE(ip)                     @ jump to next instruction
2865
2866/* ------------------------------ */
2867    .balign 64
2868.L_OP_SGET_OBJECT: /* 0x62 */
2869/* File: armv5te/OP_SGET_OBJECT.S */
2870/* File: armv5te/OP_SGET.S */
2871    /*
2872     * General 32-bit SGET handler.
2873     *
2874     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2875     */
2876    /* op vAA, field@BBBB */
2877    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2878    FETCH(r1, 1)                        @ r1<- field ref BBBB
2879    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2880    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2881    cmp     r0, #0                      @ is resolved entry null?
2882    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2883.LOP_SGET_OBJECT_finish: @ field ptr in r0
2884    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2885    mov     r2, rINST, lsr #8           @ r2<- AA
2886    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2887    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2889    GOTO_OPCODE(ip)                     @ jump to next instruction
2890
2891
2892/* ------------------------------ */
2893    .balign 64
2894.L_OP_SGET_BOOLEAN: /* 0x63 */
2895/* File: armv5te/OP_SGET_BOOLEAN.S */
2896/* File: armv5te/OP_SGET.S */
2897    /*
2898     * General 32-bit SGET handler.
2899     *
2900     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2901     */
2902    /* op vAA, field@BBBB */
2903    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2904    FETCH(r1, 1)                        @ r1<- field ref BBBB
2905    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2906    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2907    cmp     r0, #0                      @ is resolved entry null?
2908    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2909.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2910    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2911    mov     r2, rINST, lsr #8           @ r2<- AA
2912    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2913    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2914    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2915    GOTO_OPCODE(ip)                     @ jump to next instruction
2916
2917
2918/* ------------------------------ */
2919    .balign 64
2920.L_OP_SGET_BYTE: /* 0x64 */
2921/* File: armv5te/OP_SGET_BYTE.S */
2922/* File: armv5te/OP_SGET.S */
2923    /*
2924     * General 32-bit SGET handler.
2925     *
2926     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2927     */
2928    /* op vAA, field@BBBB */
2929    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2930    FETCH(r1, 1)                        @ r1<- field ref BBBB
2931    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2932    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2933    cmp     r0, #0                      @ is resolved entry null?
2934    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2935.LOP_SGET_BYTE_finish: @ field ptr in r0
2936    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2937    mov     r2, rINST, lsr #8           @ r2<- AA
2938    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2939    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2941    GOTO_OPCODE(ip)                     @ jump to next instruction
2942
2943
2944/* ------------------------------ */
2945    .balign 64
2946.L_OP_SGET_CHAR: /* 0x65 */
2947/* File: armv5te/OP_SGET_CHAR.S */
2948/* File: armv5te/OP_SGET.S */
2949    /*
2950     * General 32-bit SGET handler.
2951     *
2952     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2953     */
2954    /* op vAA, field@BBBB */
2955    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2956    FETCH(r1, 1)                        @ r1<- field ref BBBB
2957    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2958    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2959    cmp     r0, #0                      @ is resolved entry null?
2960    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2961.LOP_SGET_CHAR_finish: @ field ptr in r0
2962    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2963    mov     r2, rINST, lsr #8           @ r2<- AA
2964    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2965    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2966    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2967    GOTO_OPCODE(ip)                     @ jump to next instruction
2968
2969
2970/* ------------------------------ */
2971    .balign 64
2972.L_OP_SGET_SHORT: /* 0x66 */
2973/* File: armv5te/OP_SGET_SHORT.S */
2974/* File: armv5te/OP_SGET.S */
2975    /*
2976     * General 32-bit SGET handler.
2977     *
2978     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2979     */
2980    /* op vAA, field@BBBB */
2981    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2982    FETCH(r1, 1)                        @ r1<- field ref BBBB
2983    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2984    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2985    cmp     r0, #0                      @ is resolved entry null?
2986    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2987.LOP_SGET_SHORT_finish: @ field ptr in r0
2988    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2989    mov     r2, rINST, lsr #8           @ r2<- AA
2990    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2991    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2992    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2993    GOTO_OPCODE(ip)                     @ jump to next instruction
2994
2995
2996/* ------------------------------ */
2997    .balign 64
2998.L_OP_SPUT: /* 0x67 */
2999/* File: armv5te/OP_SPUT.S */
3000    /*
3001     * General 32-bit SPUT handler.
3002     *
3003     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3004     */
3005    /* op vAA, field@BBBB */
3006    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3007    FETCH(r1, 1)                        @ r1<- field ref BBBB
3008    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3009    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3010    cmp     r0, #0                      @ is resolved entry null?
3011    beq     .LOP_SPUT_resolve         @ yes, do resolve
3012.LOP_SPUT_finish:   @ field ptr in r0
3013    mov     r2, rINST, lsr #8           @ r2<- AA
3014    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3015    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3016    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3017    str     r1, [r0, #offStaticField_value] @ field<- vAA
3018    GOTO_OPCODE(ip)                     @ jump to next instruction
3019
3020/* ------------------------------ */
3021    .balign 64
3022.L_OP_SPUT_WIDE: /* 0x68 */
3023/* File: armv5te/OP_SPUT_WIDE.S */
3024    /*
3025     * 64-bit SPUT handler.
3026     */
3027    /* sput-wide vAA, field@BBBB */
3028    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3029    FETCH(r1, 1)                        @ r1<- field ref BBBB
3030    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3031    mov     r9, rINST, lsr #8           @ r9<- AA
3032    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3033    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3034    cmp     r0, #0                      @ is resolved entry null?
3035    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3036.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3037    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3038    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3039    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3040    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3041    GOTO_OPCODE(ip)                     @ jump to next instruction
3042
3043/* ------------------------------ */
3044    .balign 64
3045.L_OP_SPUT_OBJECT: /* 0x69 */
3046/* File: armv5te/OP_SPUT_OBJECT.S */
3047/* File: armv5te/OP_SPUT.S */
3048    /*
3049     * General 32-bit SPUT handler.
3050     *
3051     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3052     */
3053    /* op vAA, field@BBBB */
3054    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3055    FETCH(r1, 1)                        @ r1<- field ref BBBB
3056    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3057    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3058    cmp     r0, #0                      @ is resolved entry null?
3059    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3060.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3061    mov     r2, rINST, lsr #8           @ r2<- AA
3062    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3063    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3064    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3065    str     r1, [r0, #offStaticField_value] @ field<- vAA
3066    GOTO_OPCODE(ip)                     @ jump to next instruction
3067
3068
3069/* ------------------------------ */
3070    .balign 64
3071.L_OP_SPUT_BOOLEAN: /* 0x6a */
3072/* File: armv5te/OP_SPUT_BOOLEAN.S */
3073/* File: armv5te/OP_SPUT.S */
3074    /*
3075     * General 32-bit SPUT handler.
3076     *
3077     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3078     */
3079    /* op vAA, field@BBBB */
3080    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3081    FETCH(r1, 1)                        @ r1<- field ref BBBB
3082    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3083    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3084    cmp     r0, #0                      @ is resolved entry null?
3085    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3086.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3087    mov     r2, rINST, lsr #8           @ r2<- AA
3088    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3089    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3090    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3091    str     r1, [r0, #offStaticField_value] @ field<- vAA
3092    GOTO_OPCODE(ip)                     @ jump to next instruction
3093
3094
3095/* ------------------------------ */
3096    .balign 64
3097.L_OP_SPUT_BYTE: /* 0x6b */
3098/* File: armv5te/OP_SPUT_BYTE.S */
3099/* File: armv5te/OP_SPUT.S */
3100    /*
3101     * General 32-bit SPUT handler.
3102     *
3103     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3104     */
3105    /* op vAA, field@BBBB */
3106    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3107    FETCH(r1, 1)                        @ r1<- field ref BBBB
3108    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3109    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3110    cmp     r0, #0                      @ is resolved entry null?
3111    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3112.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3113    mov     r2, rINST, lsr #8           @ r2<- AA
3114    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3115    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3117    str     r1, [r0, #offStaticField_value] @ field<- vAA
3118    GOTO_OPCODE(ip)                     @ jump to next instruction
3119
3120
3121/* ------------------------------ */
3122    .balign 64
3123.L_OP_SPUT_CHAR: /* 0x6c */
3124/* File: armv5te/OP_SPUT_CHAR.S */
3125/* File: armv5te/OP_SPUT.S */
3126    /*
3127     * General 32-bit SPUT handler.
3128     *
3129     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3130     */
3131    /* op vAA, field@BBBB */
3132    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3133    FETCH(r1, 1)                        @ r1<- field ref BBBB
3134    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3135    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3136    cmp     r0, #0                      @ is resolved entry null?
3137    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3138.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3139    mov     r2, rINST, lsr #8           @ r2<- AA
3140    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3141    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3143    str     r1, [r0, #offStaticField_value] @ field<- vAA
3144    GOTO_OPCODE(ip)                     @ jump to next instruction
3145
3146
3147/* ------------------------------ */
3148    .balign 64
3149.L_OP_SPUT_SHORT: /* 0x6d */
3150/* File: armv5te/OP_SPUT_SHORT.S */
3151/* File: armv5te/OP_SPUT.S */
3152    /*
3153     * General 32-bit SPUT handler.
3154     *
3155     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3156     */
3157    /* op vAA, field@BBBB */
3158    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3159    FETCH(r1, 1)                        @ r1<- field ref BBBB
3160    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3161    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3162    cmp     r0, #0                      @ is resolved entry null?
3163    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3164.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3165    mov     r2, rINST, lsr #8           @ r2<- AA
3166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3167    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3169    str     r1, [r0, #offStaticField_value] @ field<- vAA
3170    GOTO_OPCODE(ip)                     @ jump to next instruction
3171
3172
3173/* ------------------------------ */
3174    .balign 64
3175.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3176/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3177    /*
3178     * Handle a virtual method call.
3179     *
3180     * for: invoke-virtual, invoke-virtual/range
3181     */
3182    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3183    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3184    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3185    FETCH(r1, 1)                        @ r1<- BBBB
3186    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3187    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3188    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3189    .if     (!0)
3190    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3191    .endif
3192    cmp     r0, #0                      @ already resolved?
3193    EXPORT_PC()                         @ must export for invoke
3194    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3195    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3196    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3197    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3198    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3199    cmp     r0, #0                      @ got null?
3200    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3201    b       common_exceptionThrown      @ yes, handle exception
3202
3203/* ------------------------------ */
3204    .balign 64
3205.L_OP_INVOKE_SUPER: /* 0x6f */
3206/* File: armv5te/OP_INVOKE_SUPER.S */
3207    /*
3208     * Handle a "super" method call.
3209     *
3210     * for: invoke-super, invoke-super/range
3211     */
3212    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3213    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3214    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3215    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3216    .if     (!0)
3217    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3218    .endif
3219    FETCH(r1, 1)                        @ r1<- BBBB
3220    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3221    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3222    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3223    cmp     r2, #0                      @ null "this"?
3224    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3225    beq     common_errNullObject        @ null "this", throw exception
3226    cmp     r0, #0                      @ already resolved?
3227    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3228    EXPORT_PC()                         @ must export for invoke
3229    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3230    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3231
3232/* ------------------------------ */
3233    .balign 64
3234.L_OP_INVOKE_DIRECT: /* 0x70 */
3235/* File: armv5te/OP_INVOKE_DIRECT.S */
3236    /*
3237     * Handle a direct method call.
3238     *
3239     * (We could defer the "is 'this' pointer null" test to the common
3240     * method invocation code, and use a flag to indicate that static
3241     * calls don't count.  If we do this as part of copying the arguments
3242     * out we could avoiding loading the first arg twice.)
3243     *
3244     * for: invoke-direct, invoke-direct/range
3245     */
3246    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3247    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3248    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3249    FETCH(r1, 1)                        @ r1<- BBBB
3250    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3251    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3252    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3253    .if     (!0)
3254    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3255    .endif
3256    cmp     r0, #0                      @ already resolved?
3257    EXPORT_PC()                         @ must export for invoke
3258    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3259    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3260.LOP_INVOKE_DIRECT_finish:
3261    cmp     r2, #0                      @ null "this" ref?
3262    bne     common_invokeMethodNoRange   @ no, continue on
3263    b       common_errNullObject        @ yes, throw exception
3264
3265/* ------------------------------ */
3266    .balign 64
3267.L_OP_INVOKE_STATIC: /* 0x71 */
3268/* File: armv5te/OP_INVOKE_STATIC.S */
3269    /*
3270     * Handle a static method call.
3271     *
3272     * for: invoke-static, invoke-static/range
3273     */
3274    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3275    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3276    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3277    FETCH(r1, 1)                        @ r1<- BBBB
3278    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3279    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3280    cmp     r0, #0                      @ already resolved?
3281    EXPORT_PC()                         @ must export for invoke
3282    bne     common_invokeMethodNoRange @ yes, continue on
32830:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3284    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3285    mov     r2, #METHOD_STATIC          @ resolver method type
3286    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3287    cmp     r0, #0                      @ got null?
3288    bne     common_invokeMethodNoRange @ no, continue
3289    b       common_exceptionThrown      @ yes, handle exception
3290
3291
3292/* ------------------------------ */
3293    .balign 64
3294.L_OP_INVOKE_INTERFACE: /* 0x72 */
3295/* File: armv5te/OP_INVOKE_INTERFACE.S */
3296    /*
3297     * Handle an interface method call.
3298     *
3299     * for: invoke-interface, invoke-interface/range
3300     */
3301    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3304    FETCH(r1, 1)                        @ r1<- BBBB
3305    .if     (!0)
3306    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3307    .endif
3308    EXPORT_PC()                         @ must export for invoke
3309    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3310    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3311    cmp     r0, #0                      @ null obj?
3312    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3313    beq     common_errNullObject        @ yes, fail
3314    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3315    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3316    cmp     r0, #0                      @ failed?
3317    beq     common_exceptionThrown      @ yes, handle exception
3318    b       common_invokeMethodNoRange @ jump to common handler
3319
3320
3321/* ------------------------------ */
3322    .balign 64
3323.L_OP_UNUSED_73: /* 0x73 */
3324/* File: armv5te/OP_UNUSED_73.S */
3325/* File: armv5te/unused.S */
3326    bl      common_abort
3327
3328
3329
3330/* ------------------------------ */
3331    .balign 64
3332.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3333/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3334/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3335    /*
3336     * Handle a virtual method call.
3337     *
3338     * for: invoke-virtual, invoke-virtual/range
3339     */
3340    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3341    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3342    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3343    FETCH(r1, 1)                        @ r1<- BBBB
3344    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3345    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3346    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3347    .if     (!1)
3348    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3349    .endif
3350    cmp     r0, #0                      @ already resolved?
3351    EXPORT_PC()                         @ must export for invoke
3352    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3353    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3354    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3355    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3356    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3357    cmp     r0, #0                      @ got null?
3358    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3359    b       common_exceptionThrown      @ yes, handle exception
3360
3361
3362/* ------------------------------ */
3363    .balign 64
3364.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3365/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3366/* File: armv5te/OP_INVOKE_SUPER.S */
3367    /*
3368     * Handle a "super" method call.
3369     *
3370     * for: invoke-super, invoke-super/range
3371     */
3372    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3373    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3374    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3375    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3376    .if     (!1)
3377    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3378    .endif
3379    FETCH(r1, 1)                        @ r1<- BBBB
3380    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3381    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3382    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3383    cmp     r2, #0                      @ null "this"?
3384    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3385    beq     common_errNullObject        @ null "this", throw exception
3386    cmp     r0, #0                      @ already resolved?
3387    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3388    EXPORT_PC()                         @ must export for invoke
3389    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3390    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3391
3392
3393/* ------------------------------ */
3394    .balign 64
3395.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3396/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3397/* File: armv5te/OP_INVOKE_DIRECT.S */
3398    /*
3399     * Handle a direct method call.
3400     *
3401     * (We could defer the "is 'this' pointer null" test to the common
3402     * method invocation code, and use a flag to indicate that static
3403     * calls don't count.  If we do this as part of copying the arguments
3404     * out we could avoiding loading the first arg twice.)
3405     *
3406     * for: invoke-direct, invoke-direct/range
3407     */
3408    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3409    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3410    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3411    FETCH(r1, 1)                        @ r1<- BBBB
3412    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3413    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3414    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3415    .if     (!1)
3416    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3417    .endif
3418    cmp     r0, #0                      @ already resolved?
3419    EXPORT_PC()                         @ must export for invoke
3420    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3421    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3422.LOP_INVOKE_DIRECT_RANGE_finish:
3423    cmp     r2, #0                      @ null "this" ref?
3424    bne     common_invokeMethodRange   @ no, continue on
3425    b       common_errNullObject        @ yes, throw exception
3426
3427
3428/* ------------------------------ */
3429    .balign 64
3430.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3431/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3432/* File: armv5te/OP_INVOKE_STATIC.S */
3433    /*
3434     * Handle a static method call.
3435     *
3436     * for: invoke-static, invoke-static/range
3437     */
3438    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3439    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3440    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3441    FETCH(r1, 1)                        @ r1<- BBBB
3442    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3443    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3444    cmp     r0, #0                      @ already resolved?
3445    EXPORT_PC()                         @ must export for invoke
3446    bne     common_invokeMethodRange @ yes, continue on
34470:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3448    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3449    mov     r2, #METHOD_STATIC          @ resolver method type
3450    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3451    cmp     r0, #0                      @ got null?
3452    bne     common_invokeMethodRange @ no, continue
3453    b       common_exceptionThrown      @ yes, handle exception
3454
3455
3456
3457/* ------------------------------ */
3458    .balign 64
3459.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3460/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3461/* File: armv5te/OP_INVOKE_INTERFACE.S */
3462    /*
3463     * Handle an interface method call.
3464     *
3465     * for: invoke-interface, invoke-interface/range
3466     */
3467    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3468    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3469    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3470    FETCH(r1, 1)                        @ r1<- BBBB
3471    .if     (!1)
3472    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3473    .endif
3474    EXPORT_PC()                         @ must export for invoke
3475    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3476    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3477    cmp     r0, #0                      @ null obj?
3478    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3479    beq     common_errNullObject        @ yes, fail
3480    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3481    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3482    cmp     r0, #0                      @ failed?
3483    beq     common_exceptionThrown      @ yes, handle exception
3484    b       common_invokeMethodRange @ jump to common handler
3485
3486
3487
3488/* ------------------------------ */
3489    .balign 64
3490.L_OP_UNUSED_79: /* 0x79 */
3491/* File: armv5te/OP_UNUSED_79.S */
3492/* File: armv5te/unused.S */
3493    bl      common_abort
3494
3495
3496
3497/* ------------------------------ */
3498    .balign 64
3499.L_OP_UNUSED_7A: /* 0x7a */
3500/* File: armv5te/OP_UNUSED_7A.S */
3501/* File: armv5te/unused.S */
3502    bl      common_abort
3503
3504
3505
3506/* ------------------------------ */
3507    .balign 64
3508.L_OP_NEG_INT: /* 0x7b */
3509/* File: armv6t2/OP_NEG_INT.S */
3510/* File: armv6t2/unop.S */
3511    /*
3512     * Generic 32-bit unary operation.  Provide an "instr" line that
3513     * specifies an instruction that performs "result = op r0".
3514     * This could be an ARM instruction or a function call.
3515     *
3516     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3517     *      int-to-byte, int-to-char, int-to-short
3518     */
3519    /* unop vA, vB */
3520    mov     r3, rINST, lsr #12          @ r3<- B
3521    ubfx    r9, rINST, #8, #4           @ r9<- A
3522    GET_VREG(r0, r3)                    @ r0<- vB
3523                               @ optional op; may set condition codes
3524    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3525    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3526    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3527    SET_VREG(r0, r9)                    @ vAA<- r0
3528    GOTO_OPCODE(ip)                     @ jump to next instruction
3529    /* 8-9 instructions */
3530
3531
3532/* ------------------------------ */
3533    .balign 64
3534.L_OP_NOT_INT: /* 0x7c */
3535/* File: armv6t2/OP_NOT_INT.S */
3536/* File: armv6t2/unop.S */
3537    /*
3538     * Generic 32-bit unary operation.  Provide an "instr" line that
3539     * specifies an instruction that performs "result = op r0".
3540     * This could be an ARM instruction or a function call.
3541     *
3542     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3543     *      int-to-byte, int-to-char, int-to-short
3544     */
3545    /* unop vA, vB */
3546    mov     r3, rINST, lsr #12          @ r3<- B
3547    ubfx    r9, rINST, #8, #4           @ r9<- A
3548    GET_VREG(r0, r3)                    @ r0<- vB
3549                               @ optional op; may set condition codes
3550    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3551    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3552    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3553    SET_VREG(r0, r9)                    @ vAA<- r0
3554    GOTO_OPCODE(ip)                     @ jump to next instruction
3555    /* 8-9 instructions */
3556
3557
3558/* ------------------------------ */
3559    .balign 64
3560.L_OP_NEG_LONG: /* 0x7d */
3561/* File: armv6t2/OP_NEG_LONG.S */
3562/* File: armv6t2/unopWide.S */
3563    /*
3564     * Generic 64-bit unary operation.  Provide an "instr" line that
3565     * specifies an instruction that performs "result = op r0/r1".
3566     * This could be an ARM instruction or a function call.
3567     *
3568     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3569     */
3570    /* unop vA, vB */
3571    mov     r3, rINST, lsr #12          @ r3<- B
3572    ubfx    r9, rINST, #8, #4           @ r9<- A
3573    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3574    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3575    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3576    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3577    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3578    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3580    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3581    GOTO_OPCODE(ip)                     @ jump to next instruction
3582    /* 10-11 instructions */
3583
3584
3585
3586/* ------------------------------ */
3587    .balign 64
3588.L_OP_NOT_LONG: /* 0x7e */
3589/* File: armv6t2/OP_NOT_LONG.S */
3590/* File: armv6t2/unopWide.S */
3591    /*
3592     * Generic 64-bit unary operation.  Provide an "instr" line that
3593     * specifies an instruction that performs "result = op r0/r1".
3594     * This could be an ARM instruction or a function call.
3595     *
3596     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3597     */
3598    /* unop vA, vB */
3599    mov     r3, rINST, lsr #12          @ r3<- B
3600    ubfx    r9, rINST, #8, #4           @ r9<- A
3601    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3602    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3603    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3604    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3605    mvn     r0, r0                           @ optional op; may set condition codes
3606    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3608    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3609    GOTO_OPCODE(ip)                     @ jump to next instruction
3610    /* 10-11 instructions */
3611
3612
3613
3614/* ------------------------------ */
3615    .balign 64
3616.L_OP_NEG_FLOAT: /* 0x7f */
3617/* File: armv6t2/OP_NEG_FLOAT.S */
3618/* File: armv6t2/unop.S */
3619    /*
3620     * Generic 32-bit unary operation.  Provide an "instr" line that
3621     * specifies an instruction that performs "result = op r0".
3622     * This could be an ARM instruction or a function call.
3623     *
3624     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3625     *      int-to-byte, int-to-char, int-to-short
3626     */
3627    /* unop vA, vB */
3628    mov     r3, rINST, lsr #12          @ r3<- B
3629    ubfx    r9, rINST, #8, #4           @ r9<- A
3630    GET_VREG(r0, r3)                    @ r0<- vB
3631                               @ optional op; may set condition codes
3632    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3633    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3634    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3635    SET_VREG(r0, r9)                    @ vAA<- r0
3636    GOTO_OPCODE(ip)                     @ jump to next instruction
3637    /* 8-9 instructions */
3638
3639
3640/* ------------------------------ */
3641    .balign 64
3642.L_OP_NEG_DOUBLE: /* 0x80 */
3643/* File: armv6t2/OP_NEG_DOUBLE.S */
3644/* File: armv6t2/unopWide.S */
3645    /*
3646     * Generic 64-bit unary operation.  Provide an "instr" line that
3647     * specifies an instruction that performs "result = op r0/r1".
3648     * This could be an ARM instruction or a function call.
3649     *
3650     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3651     */
3652    /* unop vA, vB */
3653    mov     r3, rINST, lsr #12          @ r3<- B
3654    ubfx    r9, rINST, #8, #4           @ r9<- A
3655    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3656    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3657    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3658    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3659                               @ optional op; may set condition codes
3660    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3661    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3662    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3663    GOTO_OPCODE(ip)                     @ jump to next instruction
3664    /* 10-11 instructions */
3665
3666
3667
3668/* ------------------------------ */
3669    .balign 64
3670.L_OP_INT_TO_LONG: /* 0x81 */
3671/* File: armv6t2/OP_INT_TO_LONG.S */
3672/* File: armv6t2/unopWider.S */
3673    /*
3674     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3675     * that specifies an instruction that performs "result = op r0", where
3676     * "result" is a 64-bit quantity in r0/r1.
3677     *
3678     * For: int-to-long, int-to-double, float-to-long, float-to-double
3679     */
3680    /* unop vA, vB */
3681    mov     r3, rINST, lsr #12          @ r3<- B
3682    ubfx    r9, rINST, #8, #4           @ r9<- A
3683    GET_VREG(r0, r3)                    @ r0<- vB
3684    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3685                               @ optional op; may set condition codes
3686    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3687    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3689    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3690    GOTO_OPCODE(ip)                     @ jump to next instruction
3691    /* 9-10 instructions */
3692
3693
3694/* ------------------------------ */
3695    .balign 64
3696.L_OP_INT_TO_FLOAT: /* 0x82 */
3697/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3698/* File: arm-vfp/funop.S */
3699    /*
3700     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3701     * line that specifies an instruction that performs "s1 = op s0".
3702     *
3703     * for: int-to-float, float-to-int
3704     */
3705    /* unop vA, vB */
3706    mov     r3, rINST, lsr #12          @ r3<- B
3707    mov     r9, rINST, lsr #8           @ r9<- A+
3708    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3709    flds    s0, [r3]                    @ s0<- vB
3710    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3711    and     r9, r9, #15                 @ r9<- A
3712    fsitos  s1, s0                              @ s1<- op
3713    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3714    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3715    fsts    s1, [r9]                    @ vA<- s1
3716    GOTO_OPCODE(ip)                     @ jump to next instruction
3717
3718
3719/* ------------------------------ */
3720    .balign 64
3721.L_OP_INT_TO_DOUBLE: /* 0x83 */
3722/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3723/* File: arm-vfp/funopWider.S */
3724    /*
3725     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3726     * "instr" line that specifies an instruction that performs "d0 = op s0".
3727     *
3728     * For: int-to-double, float-to-double
3729     */
3730    /* unop vA, vB */
3731    mov     r3, rINST, lsr #12          @ r3<- B
3732    mov     r9, rINST, lsr #8           @ r9<- A+
3733    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3734    flds    s0, [r3]                    @ s0<- vB
3735    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3736    and     r9, r9, #15                 @ r9<- A
3737    fsitod  d0, s0                              @ d0<- op
3738    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3739    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3740    fstd    d0, [r9]                    @ vA<- d0
3741    GOTO_OPCODE(ip)                     @ jump to next instruction
3742
3743
3744/* ------------------------------ */
3745    .balign 64
3746.L_OP_LONG_TO_INT: /* 0x84 */
3747/* File: armv5te/OP_LONG_TO_INT.S */
3748/* we ignore the high word, making this equivalent to a 32-bit reg move */
3749/* File: armv5te/OP_MOVE.S */
3750    /* for move, move-object, long-to-int */
3751    /* op vA, vB */
3752    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3753    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3754    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3755    GET_VREG(r2, r1)                    @ r2<- fp[B]
3756    and     r0, r0, #15
3757    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3758    SET_VREG(r2, r0)                    @ fp[A]<- r2
3759    GOTO_OPCODE(ip)                     @ execute next instruction
3760
3761
3762
3763/* ------------------------------ */
3764    .balign 64
3765.L_OP_LONG_TO_FLOAT: /* 0x85 */
3766/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3767/* File: armv6t2/unopNarrower.S */
3768    /*
3769     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3770     * that specifies an instruction that performs "result = op r0/r1", where
3771     * "result" is a 32-bit quantity in r0.
3772     *
3773     * For: long-to-float, double-to-int, double-to-float
3774     *
3775     * (This would work for long-to-int, but that instruction is actually
3776     * an exact match for OP_MOVE.)
3777     */
3778    /* unop vA, vB */
3779    mov     r3, rINST, lsr #12          @ r3<- B
3780    ubfx    r9, rINST, #8, #4           @ r9<- A
3781    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3782    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3783    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3784                               @ optional op; may set condition codes
3785    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3786    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3787    SET_VREG(r0, r9)                    @ vA<- r0
3788    GOTO_OPCODE(ip)                     @ jump to next instruction
3789    /* 9-10 instructions */
3790
3791
3792/* ------------------------------ */
3793    .balign 64
3794.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3795/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3796/* File: armv6t2/unopWide.S */
3797    /*
3798     * Generic 64-bit unary operation.  Provide an "instr" line that
3799     * specifies an instruction that performs "result = op r0/r1".
3800     * This could be an ARM instruction or a function call.
3801     *
3802     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3803     */
3804    /* unop vA, vB */
3805    mov     r3, rINST, lsr #12          @ r3<- B
3806    ubfx    r9, rINST, #8, #4           @ r9<- A
3807    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3808    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3809    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3810    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3811                               @ optional op; may set condition codes
3812    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3813    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3814    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3815    GOTO_OPCODE(ip)                     @ jump to next instruction
3816    /* 10-11 instructions */
3817
3818
3819
3820/* ------------------------------ */
3821    .balign 64
3822.L_OP_FLOAT_TO_INT: /* 0x87 */
3823/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3824/* File: arm-vfp/funop.S */
3825    /*
3826     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3827     * line that specifies an instruction that performs "s1 = op s0".
3828     *
3829     * for: int-to-float, float-to-int
3830     */
3831    /* unop vA, vB */
3832    mov     r3, rINST, lsr #12          @ r3<- B
3833    mov     r9, rINST, lsr #8           @ r9<- A+
3834    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3835    flds    s0, [r3]                    @ s0<- vB
3836    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3837    and     r9, r9, #15                 @ r9<- A
3838    ftosizs s1, s0                              @ s1<- op
3839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3840    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3841    fsts    s1, [r9]                    @ vA<- s1
3842    GOTO_OPCODE(ip)                     @ jump to next instruction
3843
3844
3845/* ------------------------------ */
3846    .balign 64
3847.L_OP_FLOAT_TO_LONG: /* 0x88 */
3848/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3849@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3850/* File: armv6t2/unopWider.S */
3851    /*
3852     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3853     * that specifies an instruction that performs "result = op r0", where
3854     * "result" is a 64-bit quantity in r0/r1.
3855     *
3856     * For: int-to-long, int-to-double, float-to-long, float-to-double
3857     */
3858    /* unop vA, vB */
3859    mov     r3, rINST, lsr #12          @ r3<- B
3860    ubfx    r9, rINST, #8, #4           @ r9<- A
3861    GET_VREG(r0, r3)                    @ r0<- vB
3862    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3863                               @ optional op; may set condition codes
3864    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3865    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3867    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3868    GOTO_OPCODE(ip)                     @ jump to next instruction
3869    /* 9-10 instructions */
3870
3871
3872
3873/* ------------------------------ */
3874    .balign 64
3875.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3876/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3877/* File: arm-vfp/funopWider.S */
3878    /*
3879     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3880     * "instr" line that specifies an instruction that performs "d0 = op s0".
3881     *
3882     * For: int-to-double, float-to-double
3883     */
3884    /* unop vA, vB */
3885    mov     r3, rINST, lsr #12          @ r3<- B
3886    mov     r9, rINST, lsr #8           @ r9<- A+
3887    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3888    flds    s0, [r3]                    @ s0<- vB
3889    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3890    and     r9, r9, #15                 @ r9<- A
3891    fcvtds  d0, s0                              @ d0<- op
3892    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3893    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3894    fstd    d0, [r9]                    @ vA<- d0
3895    GOTO_OPCODE(ip)                     @ jump to next instruction
3896
3897
3898/* ------------------------------ */
3899    .balign 64
3900.L_OP_DOUBLE_TO_INT: /* 0x8a */
3901/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3902/* File: arm-vfp/funopNarrower.S */
3903    /*
3904     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3905     * "instr" line that specifies an instruction that performs "s0 = op d0".
3906     *
3907     * For: double-to-int, double-to-float
3908     */
3909    /* unop vA, vB */
3910    mov     r3, rINST, lsr #12          @ r3<- B
3911    mov     r9, rINST, lsr #8           @ r9<- A+
3912    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3913    fldd    d0, [r3]                    @ d0<- vB
3914    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3915    and     r9, r9, #15                 @ r9<- A
3916    ftosizd  s0, d0                              @ s0<- op
3917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3918    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3919    fsts    s0, [r9]                    @ vA<- s0
3920    GOTO_OPCODE(ip)                     @ jump to next instruction
3921
3922
3923/* ------------------------------ */
3924    .balign 64
3925.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3926/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3927@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3928/* File: armv6t2/unopWide.S */
3929    /*
3930     * Generic 64-bit unary operation.  Provide an "instr" line that
3931     * specifies an instruction that performs "result = op r0/r1".
3932     * This could be an ARM instruction or a function call.
3933     *
3934     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3935     */
3936    /* unop vA, vB */
3937    mov     r3, rINST, lsr #12          @ r3<- B
3938    ubfx    r9, rINST, #8, #4           @ r9<- A
3939    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3940    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3941    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3942    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3943                               @ optional op; may set condition codes
3944    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3946    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3947    GOTO_OPCODE(ip)                     @ jump to next instruction
3948    /* 10-11 instructions */
3949
3950
3951
3952
3953/* ------------------------------ */
3954    .balign 64
3955.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3956/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3957/* File: arm-vfp/funopNarrower.S */
3958    /*
3959     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3960     * "instr" line that specifies an instruction that performs "s0 = op d0".
3961     *
3962     * For: double-to-int, double-to-float
3963     */
3964    /* unop vA, vB */
3965    mov     r3, rINST, lsr #12          @ r3<- B
3966    mov     r9, rINST, lsr #8           @ r9<- A+
3967    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3968    fldd    d0, [r3]                    @ d0<- vB
3969    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3970    and     r9, r9, #15                 @ r9<- A
3971    fcvtsd  s0, d0                              @ s0<- op
3972    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3973    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3974    fsts    s0, [r9]                    @ vA<- s0
3975    GOTO_OPCODE(ip)                     @ jump to next instruction
3976
3977
3978/* ------------------------------ */
3979    .balign 64
3980.L_OP_INT_TO_BYTE: /* 0x8d */
3981/* File: armv6t2/OP_INT_TO_BYTE.S */
3982/* File: armv6t2/unop.S */
3983    /*
3984     * Generic 32-bit unary operation.  Provide an "instr" line that
3985     * specifies an instruction that performs "result = op r0".
3986     * This could be an ARM instruction or a function call.
3987     *
3988     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3989     *      int-to-byte, int-to-char, int-to-short
3990     */
3991    /* unop vA, vB */
3992    mov     r3, rINST, lsr #12          @ r3<- B
3993    ubfx    r9, rINST, #8, #4           @ r9<- A
3994    GET_VREG(r0, r3)                    @ r0<- vB
3995                               @ optional op; may set condition codes
3996    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3997    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3999    SET_VREG(r0, r9)                    @ vAA<- r0
4000    GOTO_OPCODE(ip)                     @ jump to next instruction
4001    /* 8-9 instructions */
4002
4003
4004/* ------------------------------ */
4005    .balign 64
4006.L_OP_INT_TO_CHAR: /* 0x8e */
4007/* File: armv6t2/OP_INT_TO_CHAR.S */
4008/* File: armv6t2/unop.S */
4009    /*
4010     * Generic 32-bit unary operation.  Provide an "instr" line that
4011     * specifies an instruction that performs "result = op r0".
4012     * This could be an ARM instruction or a function call.
4013     *
4014     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4015     *      int-to-byte, int-to-char, int-to-short
4016     */
4017    /* unop vA, vB */
4018    mov     r3, rINST, lsr #12          @ r3<- B
4019    ubfx    r9, rINST, #8, #4           @ r9<- A
4020    GET_VREG(r0, r3)                    @ r0<- vB
4021                               @ optional op; may set condition codes
4022    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4023    uxth    r0, r0                              @ r0<- op, r0-r3 changed
4024    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4025    SET_VREG(r0, r9)                    @ vAA<- r0
4026    GOTO_OPCODE(ip)                     @ jump to next instruction
4027    /* 8-9 instructions */
4028
4029
4030/* ------------------------------ */
4031    .balign 64
4032.L_OP_INT_TO_SHORT: /* 0x8f */
4033/* File: armv6t2/OP_INT_TO_SHORT.S */
4034/* File: armv6t2/unop.S */
4035    /*
4036     * Generic 32-bit unary operation.  Provide an "instr" line that
4037     * specifies an instruction that performs "result = op r0".
4038     * This could be an ARM instruction or a function call.
4039     *
4040     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4041     *      int-to-byte, int-to-char, int-to-short
4042     */
4043    /* unop vA, vB */
4044    mov     r3, rINST, lsr #12          @ r3<- B
4045    ubfx    r9, rINST, #8, #4           @ r9<- A
4046    GET_VREG(r0, r3)                    @ r0<- vB
4047                               @ optional op; may set condition codes
4048    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4049    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4051    SET_VREG(r0, r9)                    @ vAA<- r0
4052    GOTO_OPCODE(ip)                     @ jump to next instruction
4053    /* 8-9 instructions */
4054
4055
4056/* ------------------------------ */
4057    .balign 64
4058.L_OP_ADD_INT: /* 0x90 */
4059/* File: armv5te/OP_ADD_INT.S */
4060/* File: armv5te/binop.S */
4061    /*
4062     * Generic 32-bit binary operation.  Provide an "instr" line that
4063     * specifies an instruction that performs "result = r0 op r1".
4064     * This could be an ARM instruction or a function call.  (If the result
4065     * comes back in a register other than r0, you can override "result".)
4066     *
4067     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4068     * vCC (r1).  Useful for integer division and modulus.  Note that we
4069     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4070     * handles it correctly.
4071     *
4072     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4073     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4074     *      mul-float, div-float, rem-float
4075     */
4076    /* binop vAA, vBB, vCC */
4077    FETCH(r0, 1)                        @ r0<- CCBB
4078    mov     r9, rINST, lsr #8           @ r9<- AA
4079    mov     r3, r0, lsr #8              @ r3<- CC
4080    and     r2, r0, #255                @ r2<- BB
4081    GET_VREG(r1, r3)                    @ r1<- vCC
4082    GET_VREG(r0, r2)                    @ r0<- vBB
4083    .if 0
4084    cmp     r1, #0                      @ is second operand zero?
4085    beq     common_errDivideByZero
4086    .endif
4087
4088    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4089                               @ optional op; may set condition codes
4090    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4091    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4092    SET_VREG(r0, r9)               @ vAA<- r0
4093    GOTO_OPCODE(ip)                     @ jump to next instruction
4094    /* 11-14 instructions */
4095
4096
4097
4098/* ------------------------------ */
4099    .balign 64
4100.L_OP_SUB_INT: /* 0x91 */
4101/* File: armv5te/OP_SUB_INT.S */
4102/* File: armv5te/binop.S */
4103    /*
4104     * Generic 32-bit binary operation.  Provide an "instr" line that
4105     * specifies an instruction that performs "result = r0 op r1".
4106     * This could be an ARM instruction or a function call.  (If the result
4107     * comes back in a register other than r0, you can override "result".)
4108     *
4109     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4110     * vCC (r1).  Useful for integer division and modulus.  Note that we
4111     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4112     * handles it correctly.
4113     *
4114     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4115     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4116     *      mul-float, div-float, rem-float
4117     */
4118    /* binop vAA, vBB, vCC */
4119    FETCH(r0, 1)                        @ r0<- CCBB
4120    mov     r9, rINST, lsr #8           @ r9<- AA
4121    mov     r3, r0, lsr #8              @ r3<- CC
4122    and     r2, r0, #255                @ r2<- BB
4123    GET_VREG(r1, r3)                    @ r1<- vCC
4124    GET_VREG(r0, r2)                    @ r0<- vBB
4125    .if 0
4126    cmp     r1, #0                      @ is second operand zero?
4127    beq     common_errDivideByZero
4128    .endif
4129
4130    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4131                               @ optional op; may set condition codes
4132    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4134    SET_VREG(r0, r9)               @ vAA<- r0
4135    GOTO_OPCODE(ip)                     @ jump to next instruction
4136    /* 11-14 instructions */
4137
4138
4139
4140/* ------------------------------ */
4141    .balign 64
4142.L_OP_MUL_INT: /* 0x92 */
4143/* File: armv5te/OP_MUL_INT.S */
4144/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4145/* File: armv5te/binop.S */
4146    /*
4147     * Generic 32-bit binary operation.  Provide an "instr" line that
4148     * specifies an instruction that performs "result = r0 op r1".
4149     * This could be an ARM instruction or a function call.  (If the result
4150     * comes back in a register other than r0, you can override "result".)
4151     *
4152     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4153     * vCC (r1).  Useful for integer division and modulus.  Note that we
4154     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4155     * handles it correctly.
4156     *
4157     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4158     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4159     *      mul-float, div-float, rem-float
4160     */
4161    /* binop vAA, vBB, vCC */
4162    FETCH(r0, 1)                        @ r0<- CCBB
4163    mov     r9, rINST, lsr #8           @ r9<- AA
4164    mov     r3, r0, lsr #8              @ r3<- CC
4165    and     r2, r0, #255                @ r2<- BB
4166    GET_VREG(r1, r3)                    @ r1<- vCC
4167    GET_VREG(r0, r2)                    @ r0<- vBB
4168    .if 0
4169    cmp     r1, #0                      @ is second operand zero?
4170    beq     common_errDivideByZero
4171    .endif
4172
4173    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4174                               @ optional op; may set condition codes
4175    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4177    SET_VREG(r0, r9)               @ vAA<- r0
4178    GOTO_OPCODE(ip)                     @ jump to next instruction
4179    /* 11-14 instructions */
4180
4181
4182
4183/* ------------------------------ */
4184    .balign 64
4185.L_OP_DIV_INT: /* 0x93 */
4186/* File: armv5te/OP_DIV_INT.S */
4187/* File: armv5te/binop.S */
4188    /*
4189     * Generic 32-bit binary operation.  Provide an "instr" line that
4190     * specifies an instruction that performs "result = r0 op r1".
4191     * This could be an ARM instruction or a function call.  (If the result
4192     * comes back in a register other than r0, you can override "result".)
4193     *
4194     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4195     * vCC (r1).  Useful for integer division and modulus.  Note that we
4196     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4197     * handles it correctly.
4198     *
4199     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4200     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4201     *      mul-float, div-float, rem-float
4202     */
4203    /* binop vAA, vBB, vCC */
4204    FETCH(r0, 1)                        @ r0<- CCBB
4205    mov     r9, rINST, lsr #8           @ r9<- AA
4206    mov     r3, r0, lsr #8              @ r3<- CC
4207    and     r2, r0, #255                @ r2<- BB
4208    GET_VREG(r1, r3)                    @ r1<- vCC
4209    GET_VREG(r0, r2)                    @ r0<- vBB
4210    .if 1
4211    cmp     r1, #0                      @ is second operand zero?
4212    beq     common_errDivideByZero
4213    .endif
4214
4215    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4216                               @ optional op; may set condition codes
4217    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4219    SET_VREG(r0, r9)               @ vAA<- r0
4220    GOTO_OPCODE(ip)                     @ jump to next instruction
4221    /* 11-14 instructions */
4222
4223
4224
4225/* ------------------------------ */
4226    .balign 64
4227.L_OP_REM_INT: /* 0x94 */
4228/* File: armv5te/OP_REM_INT.S */
4229/* idivmod returns quotient in r0 and remainder in r1 */
4230/* File: armv5te/binop.S */
4231    /*
4232     * Generic 32-bit binary operation.  Provide an "instr" line that
4233     * specifies an instruction that performs "result = r0 op r1".
4234     * This could be an ARM instruction or a function call.  (If the result
4235     * comes back in a register other than r0, you can override "result".)
4236     *
4237     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4238     * vCC (r1).  Useful for integer division and modulus.  Note that we
4239     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4240     * handles it correctly.
4241     *
4242     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4243     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4244     *      mul-float, div-float, rem-float
4245     */
4246    /* binop vAA, vBB, vCC */
4247    FETCH(r0, 1)                        @ r0<- CCBB
4248    mov     r9, rINST, lsr #8           @ r9<- AA
4249    mov     r3, r0, lsr #8              @ r3<- CC
4250    and     r2, r0, #255                @ r2<- BB
4251    GET_VREG(r1, r3)                    @ r1<- vCC
4252    GET_VREG(r0, r2)                    @ r0<- vBB
4253    .if 1
4254    cmp     r1, #0                      @ is second operand zero?
4255    beq     common_errDivideByZero
4256    .endif
4257
4258    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4259                               @ optional op; may set condition codes
4260    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4261    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4262    SET_VREG(r1, r9)               @ vAA<- r1
4263    GOTO_OPCODE(ip)                     @ jump to next instruction
4264    /* 11-14 instructions */
4265
4266
4267
4268/* ------------------------------ */
4269    .balign 64
4270.L_OP_AND_INT: /* 0x95 */
4271/* File: armv5te/OP_AND_INT.S */
4272/* File: armv5te/binop.S */
4273    /*
4274     * Generic 32-bit binary operation.  Provide an "instr" line that
4275     * specifies an instruction that performs "result = r0 op r1".
4276     * This could be an ARM instruction or a function call.  (If the result
4277     * comes back in a register other than r0, you can override "result".)
4278     *
4279     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4280     * vCC (r1).  Useful for integer division and modulus.  Note that we
4281     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4282     * handles it correctly.
4283     *
4284     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4285     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4286     *      mul-float, div-float, rem-float
4287     */
4288    /* binop vAA, vBB, vCC */
4289    FETCH(r0, 1)                        @ r0<- CCBB
4290    mov     r9, rINST, lsr #8           @ r9<- AA
4291    mov     r3, r0, lsr #8              @ r3<- CC
4292    and     r2, r0, #255                @ r2<- BB
4293    GET_VREG(r1, r3)                    @ r1<- vCC
4294    GET_VREG(r0, r2)                    @ r0<- vBB
4295    .if 0
4296    cmp     r1, #0                      @ is second operand zero?
4297    beq     common_errDivideByZero
4298    .endif
4299
4300    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4301                               @ optional op; may set condition codes
4302    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4304    SET_VREG(r0, r9)               @ vAA<- r0
4305    GOTO_OPCODE(ip)                     @ jump to next instruction
4306    /* 11-14 instructions */
4307
4308
4309
4310/* ------------------------------ */
4311    .balign 64
4312.L_OP_OR_INT: /* 0x96 */
4313/* File: armv5te/OP_OR_INT.S */
4314/* File: armv5te/binop.S */
4315    /*
4316     * Generic 32-bit binary operation.  Provide an "instr" line that
4317     * specifies an instruction that performs "result = r0 op r1".
4318     * This could be an ARM instruction or a function call.  (If the result
4319     * comes back in a register other than r0, you can override "result".)
4320     *
4321     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4322     * vCC (r1).  Useful for integer division and modulus.  Note that we
4323     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4324     * handles it correctly.
4325     *
4326     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4327     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4328     *      mul-float, div-float, rem-float
4329     */
4330    /* binop vAA, vBB, vCC */
4331    FETCH(r0, 1)                        @ r0<- CCBB
4332    mov     r9, rINST, lsr #8           @ r9<- AA
4333    mov     r3, r0, lsr #8              @ r3<- CC
4334    and     r2, r0, #255                @ r2<- BB
4335    GET_VREG(r1, r3)                    @ r1<- vCC
4336    GET_VREG(r0, r2)                    @ r0<- vBB
4337    .if 0
4338    cmp     r1, #0                      @ is second operand zero?
4339    beq     common_errDivideByZero
4340    .endif
4341
4342    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4343                               @ optional op; may set condition codes
4344    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4346    SET_VREG(r0, r9)               @ vAA<- r0
4347    GOTO_OPCODE(ip)                     @ jump to next instruction
4348    /* 11-14 instructions */
4349
4350
4351
4352/* ------------------------------ */
4353    .balign 64
4354.L_OP_XOR_INT: /* 0x97 */
4355/* File: armv5te/OP_XOR_INT.S */
4356/* File: armv5te/binop.S */
4357    /*
4358     * Generic 32-bit binary operation.  Provide an "instr" line that
4359     * specifies an instruction that performs "result = r0 op r1".
4360     * This could be an ARM instruction or a function call.  (If the result
4361     * comes back in a register other than r0, you can override "result".)
4362     *
4363     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4364     * vCC (r1).  Useful for integer division and modulus.  Note that we
4365     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4366     * handles it correctly.
4367     *
4368     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4369     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4370     *      mul-float, div-float, rem-float
4371     */
4372    /* binop vAA, vBB, vCC */
4373    FETCH(r0, 1)                        @ r0<- CCBB
4374    mov     r9, rINST, lsr #8           @ r9<- AA
4375    mov     r3, r0, lsr #8              @ r3<- CC
4376    and     r2, r0, #255                @ r2<- BB
4377    GET_VREG(r1, r3)                    @ r1<- vCC
4378    GET_VREG(r0, r2)                    @ r0<- vBB
4379    .if 0
4380    cmp     r1, #0                      @ is second operand zero?
4381    beq     common_errDivideByZero
4382    .endif
4383
4384    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4385                               @ optional op; may set condition codes
4386    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4388    SET_VREG(r0, r9)               @ vAA<- r0
4389    GOTO_OPCODE(ip)                     @ jump to next instruction
4390    /* 11-14 instructions */
4391
4392
4393
4394/* ------------------------------ */
4395    .balign 64
4396.L_OP_SHL_INT: /* 0x98 */
4397/* File: armv5te/OP_SHL_INT.S */
4398/* File: armv5te/binop.S */
4399    /*
4400     * Generic 32-bit binary operation.  Provide an "instr" line that
4401     * specifies an instruction that performs "result = r0 op r1".
4402     * This could be an ARM instruction or a function call.  (If the result
4403     * comes back in a register other than r0, you can override "result".)
4404     *
4405     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4406     * vCC (r1).  Useful for integer division and modulus.  Note that we
4407     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4408     * handles it correctly.
4409     *
4410     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4411     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4412     *      mul-float, div-float, rem-float
4413     */
4414    /* binop vAA, vBB, vCC */
4415    FETCH(r0, 1)                        @ r0<- CCBB
4416    mov     r9, rINST, lsr #8           @ r9<- AA
4417    mov     r3, r0, lsr #8              @ r3<- CC
4418    and     r2, r0, #255                @ r2<- BB
4419    GET_VREG(r1, r3)                    @ r1<- vCC
4420    GET_VREG(r0, r2)                    @ r0<- vBB
4421    .if 0
4422    cmp     r1, #0                      @ is second operand zero?
4423    beq     common_errDivideByZero
4424    .endif
4425
4426    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4427    and     r1, r1, #31                           @ optional op; may set condition codes
4428    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4429    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4430    SET_VREG(r0, r9)               @ vAA<- r0
4431    GOTO_OPCODE(ip)                     @ jump to next instruction
4432    /* 11-14 instructions */
4433
4434
4435
4436/* ------------------------------ */
4437    .balign 64
4438.L_OP_SHR_INT: /* 0x99 */
4439/* File: armv5te/OP_SHR_INT.S */
4440/* File: armv5te/binop.S */
4441    /*
4442     * Generic 32-bit binary operation.  Provide an "instr" line that
4443     * specifies an instruction that performs "result = r0 op r1".
4444     * This could be an ARM instruction or a function call.  (If the result
4445     * comes back in a register other than r0, you can override "result".)
4446     *
4447     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4448     * vCC (r1).  Useful for integer division and modulus.  Note that we
4449     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4450     * handles it correctly.
4451     *
4452     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4453     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4454     *      mul-float, div-float, rem-float
4455     */
4456    /* binop vAA, vBB, vCC */
4457    FETCH(r0, 1)                        @ r0<- CCBB
4458    mov     r9, rINST, lsr #8           @ r9<- AA
4459    mov     r3, r0, lsr #8              @ r3<- CC
4460    and     r2, r0, #255                @ r2<- BB
4461    GET_VREG(r1, r3)                    @ r1<- vCC
4462    GET_VREG(r0, r2)                    @ r0<- vBB
4463    .if 0
4464    cmp     r1, #0                      @ is second operand zero?
4465    beq     common_errDivideByZero
4466    .endif
4467
4468    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4469    and     r1, r1, #31                           @ optional op; may set condition codes
4470    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4471    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4472    SET_VREG(r0, r9)               @ vAA<- r0
4473    GOTO_OPCODE(ip)                     @ jump to next instruction
4474    /* 11-14 instructions */
4475
4476
4477
4478/* ------------------------------ */
4479    .balign 64
4480.L_OP_USHR_INT: /* 0x9a */
4481/* File: armv5te/OP_USHR_INT.S */
4482/* File: armv5te/binop.S */
4483    /*
4484     * Generic 32-bit binary operation.  Provide an "instr" line that
4485     * specifies an instruction that performs "result = r0 op r1".
4486     * This could be an ARM instruction or a function call.  (If the result
4487     * comes back in a register other than r0, you can override "result".)
4488     *
4489     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4490     * vCC (r1).  Useful for integer division and modulus.  Note that we
4491     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4492     * handles it correctly.
4493     *
4494     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4495     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4496     *      mul-float, div-float, rem-float
4497     */
4498    /* binop vAA, vBB, vCC */
4499    FETCH(r0, 1)                        @ r0<- CCBB
4500    mov     r9, rINST, lsr #8           @ r9<- AA
4501    mov     r3, r0, lsr #8              @ r3<- CC
4502    and     r2, r0, #255                @ r2<- BB
4503    GET_VREG(r1, r3)                    @ r1<- vCC
4504    GET_VREG(r0, r2)                    @ r0<- vBB
4505    .if 0
4506    cmp     r1, #0                      @ is second operand zero?
4507    beq     common_errDivideByZero
4508    .endif
4509
4510    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4511    and     r1, r1, #31                           @ optional op; may set condition codes
4512    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4514    SET_VREG(r0, r9)               @ vAA<- r0
4515    GOTO_OPCODE(ip)                     @ jump to next instruction
4516    /* 11-14 instructions */
4517
4518
4519
4520/* ------------------------------ */
4521    .balign 64
4522.L_OP_ADD_LONG: /* 0x9b */
4523/* File: armv5te/OP_ADD_LONG.S */
4524/* File: armv5te/binopWide.S */
4525    /*
4526     * Generic 64-bit binary operation.  Provide an "instr" line that
4527     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4528     * This could be an ARM instruction or a function call.  (If the result
4529     * comes back in a register other than r0, you can override "result".)
4530     *
4531     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4532     * vCC (r1).  Useful for integer division and modulus.
4533     *
4534     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4535     *      xor-long, add-double, sub-double, mul-double, div-double,
4536     *      rem-double
4537     *
4538     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4539     */
4540    /* binop vAA, vBB, vCC */
4541    FETCH(r0, 1)                        @ r0<- CCBB
4542    mov     r9, rINST, lsr #8           @ r9<- AA
4543    and     r2, r0, #255                @ r2<- BB
4544    mov     r3, r0, lsr #8              @ r3<- CC
4545    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4546    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4547    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4548    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4549    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4550    .if 0
4551    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4552    beq     common_errDivideByZero
4553    .endif
4554    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4555
4556    adds    r0, r0, r2                           @ optional op; may set condition codes
4557    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4559    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4560    GOTO_OPCODE(ip)                     @ jump to next instruction
4561    /* 14-17 instructions */
4562
4563
4564
4565/* ------------------------------ */
4566    .balign 64
4567.L_OP_SUB_LONG: /* 0x9c */
4568/* File: armv5te/OP_SUB_LONG.S */
4569/* File: armv5te/binopWide.S */
4570    /*
4571     * Generic 64-bit binary operation.  Provide an "instr" line that
4572     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4573     * This could be an ARM instruction or a function call.  (If the result
4574     * comes back in a register other than r0, you can override "result".)
4575     *
4576     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4577     * vCC (r1).  Useful for integer division and modulus.
4578     *
4579     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4580     *      xor-long, add-double, sub-double, mul-double, div-double,
4581     *      rem-double
4582     *
4583     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4584     */
4585    /* binop vAA, vBB, vCC */
4586    FETCH(r0, 1)                        @ r0<- CCBB
4587    mov     r9, rINST, lsr #8           @ r9<- AA
4588    and     r2, r0, #255                @ r2<- BB
4589    mov     r3, r0, lsr #8              @ r3<- CC
4590    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4591    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4592    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4593    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4594    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4595    .if 0
4596    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4597    beq     common_errDivideByZero
4598    .endif
4599    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4600
4601    subs    r0, r0, r2                           @ optional op; may set condition codes
4602    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4603    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4604    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4605    GOTO_OPCODE(ip)                     @ jump to next instruction
4606    /* 14-17 instructions */
4607
4608
4609
4610/* ------------------------------ */
4611    .balign 64
4612.L_OP_MUL_LONG: /* 0x9d */
4613/* File: armv5te/OP_MUL_LONG.S */
4614    /*
4615     * Signed 64-bit integer multiply.
4616     *
4617     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4618     *        WX
4619     *      x YZ
4620     *  --------
4621     *     ZW ZX
4622     *  YW YX
4623     *
4624     * The low word of the result holds ZX, the high word holds
4625     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4626     * it doesn't fit in the low 64 bits.
4627     *
4628     * Unlike most ARM math operations, multiply instructions have
4629     * restrictions on using the same register more than once (Rd and Rm
4630     * cannot be the same).
4631     */
4632    /* mul-long vAA, vBB, vCC */
4633    FETCH(r0, 1)                        @ r0<- CCBB
4634    and     r2, r0, #255                @ r2<- BB
4635    mov     r3, r0, lsr #8              @ r3<- CC
4636    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4637    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4638    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4639    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4640    mul     ip, r2, r1                  @  ip<- ZxW
4641    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4642    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4643    mov     r0, rINST, lsr #8           @ r0<- AA
4644    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4645    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4646    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4647    b       .LOP_MUL_LONG_finish
4648
4649/* ------------------------------ */
4650    .balign 64
4651.L_OP_DIV_LONG: /* 0x9e */
4652/* File: armv5te/OP_DIV_LONG.S */
4653/* File: armv5te/binopWide.S */
4654    /*
4655     * Generic 64-bit binary operation.  Provide an "instr" line that
4656     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4657     * This could be an ARM instruction or a function call.  (If the result
4658     * comes back in a register other than r0, you can override "result".)
4659     *
4660     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4661     * vCC (r1).  Useful for integer division and modulus.
4662     *
4663     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4664     *      xor-long, add-double, sub-double, mul-double, div-double,
4665     *      rem-double
4666     *
4667     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4668     */
4669    /* binop vAA, vBB, vCC */
4670    FETCH(r0, 1)                        @ r0<- CCBB
4671    mov     r9, rINST, lsr #8           @ r9<- AA
4672    and     r2, r0, #255                @ r2<- BB
4673    mov     r3, r0, lsr #8              @ r3<- CC
4674    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4675    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4676    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4677    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4678    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4679    .if 1
4680    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4681    beq     common_errDivideByZero
4682    .endif
4683    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4684
4685                               @ optional op; may set condition codes
4686    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4687    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4688    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4689    GOTO_OPCODE(ip)                     @ jump to next instruction
4690    /* 14-17 instructions */
4691
4692
4693
4694/* ------------------------------ */
4695    .balign 64
4696.L_OP_REM_LONG: /* 0x9f */
4697/* File: armv5te/OP_REM_LONG.S */
4698/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4699/* File: armv5te/binopWide.S */
4700    /*
4701     * Generic 64-bit binary operation.  Provide an "instr" line that
4702     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4703     * This could be an ARM instruction or a function call.  (If the result
4704     * comes back in a register other than r0, you can override "result".)
4705     *
4706     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4707     * vCC (r1).  Useful for integer division and modulus.
4708     *
4709     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4710     *      xor-long, add-double, sub-double, mul-double, div-double,
4711     *      rem-double
4712     *
4713     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4714     */
4715    /* binop vAA, vBB, vCC */
4716    FETCH(r0, 1)                        @ r0<- CCBB
4717    mov     r9, rINST, lsr #8           @ r9<- AA
4718    and     r2, r0, #255                @ r2<- BB
4719    mov     r3, r0, lsr #8              @ r3<- CC
4720    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4721    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4722    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4723    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4724    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4725    .if 1
4726    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4727    beq     common_errDivideByZero
4728    .endif
4729    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4730
4731                               @ optional op; may set condition codes
4732    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4733    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4734    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4735    GOTO_OPCODE(ip)                     @ jump to next instruction
4736    /* 14-17 instructions */
4737
4738
4739
4740/* ------------------------------ */
4741    .balign 64
4742.L_OP_AND_LONG: /* 0xa0 */
4743/* File: armv5te/OP_AND_LONG.S */
4744/* File: armv5te/binopWide.S */
4745    /*
4746     * Generic 64-bit binary operation.  Provide an "instr" line that
4747     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4748     * This could be an ARM instruction or a function call.  (If the result
4749     * comes back in a register other than r0, you can override "result".)
4750     *
4751     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4752     * vCC (r1).  Useful for integer division and modulus.
4753     *
4754     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4755     *      xor-long, add-double, sub-double, mul-double, div-double,
4756     *      rem-double
4757     *
4758     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4759     */
4760    /* binop vAA, vBB, vCC */
4761    FETCH(r0, 1)                        @ r0<- CCBB
4762    mov     r9, rINST, lsr #8           @ r9<- AA
4763    and     r2, r0, #255                @ r2<- BB
4764    mov     r3, r0, lsr #8              @ r3<- CC
4765    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4766    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4767    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4768    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4769    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4770    .if 0
4771    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4772    beq     common_errDivideByZero
4773    .endif
4774    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4775
4776    and     r0, r0, r2                           @ optional op; may set condition codes
4777    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4778    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4779    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4780    GOTO_OPCODE(ip)                     @ jump to next instruction
4781    /* 14-17 instructions */
4782
4783
4784
4785/* ------------------------------ */
4786    .balign 64
4787.L_OP_OR_LONG: /* 0xa1 */
4788/* File: armv5te/OP_OR_LONG.S */
4789/* File: armv5te/binopWide.S */
4790    /*
4791     * Generic 64-bit binary operation.  Provide an "instr" line that
4792     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4793     * This could be an ARM instruction or a function call.  (If the result
4794     * comes back in a register other than r0, you can override "result".)
4795     *
4796     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4797     * vCC (r1).  Useful for integer division and modulus.
4798     *
4799     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4800     *      xor-long, add-double, sub-double, mul-double, div-double,
4801     *      rem-double
4802     *
4803     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4804     */
4805    /* binop vAA, vBB, vCC */
4806    FETCH(r0, 1)                        @ r0<- CCBB
4807    mov     r9, rINST, lsr #8           @ r9<- AA
4808    and     r2, r0, #255                @ r2<- BB
4809    mov     r3, r0, lsr #8              @ r3<- CC
4810    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4811    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4812    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4813    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4814    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4815    .if 0
4816    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4817    beq     common_errDivideByZero
4818    .endif
4819    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4820
4821    orr     r0, r0, r2                           @ optional op; may set condition codes
4822    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4823    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4824    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4825    GOTO_OPCODE(ip)                     @ jump to next instruction
4826    /* 14-17 instructions */
4827
4828
4829
4830/* ------------------------------ */
4831    .balign 64
4832.L_OP_XOR_LONG: /* 0xa2 */
4833/* File: armv5te/OP_XOR_LONG.S */
4834/* File: armv5te/binopWide.S */
4835    /*
4836     * Generic 64-bit binary operation.  Provide an "instr" line that
4837     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4838     * This could be an ARM instruction or a function call.  (If the result
4839     * comes back in a register other than r0, you can override "result".)
4840     *
4841     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4842     * vCC (r1).  Useful for integer division and modulus.
4843     *
4844     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4845     *      xor-long, add-double, sub-double, mul-double, div-double,
4846     *      rem-double
4847     *
4848     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4849     */
4850    /* binop vAA, vBB, vCC */
4851    FETCH(r0, 1)                        @ r0<- CCBB
4852    mov     r9, rINST, lsr #8           @ r9<- AA
4853    and     r2, r0, #255                @ r2<- BB
4854    mov     r3, r0, lsr #8              @ r3<- CC
4855    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4856    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4857    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4858    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4859    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4860    .if 0
4861    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4862    beq     common_errDivideByZero
4863    .endif
4864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4865
4866    eor     r0, r0, r2                           @ optional op; may set condition codes
4867    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4869    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4870    GOTO_OPCODE(ip)                     @ jump to next instruction
4871    /* 14-17 instructions */
4872
4873
4874
4875/* ------------------------------ */
4876    .balign 64
4877.L_OP_SHL_LONG: /* 0xa3 */
4878/* File: armv5te/OP_SHL_LONG.S */
4879    /*
4880     * Long integer shift.  This is different from the generic 32/64-bit
4881     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4882     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4883     * 6 bits of the shift distance.
4884     */
4885    /* shl-long vAA, vBB, vCC */
4886    FETCH(r0, 1)                        @ r0<- CCBB
4887    mov     r9, rINST, lsr #8           @ r9<- AA
4888    and     r3, r0, #255                @ r3<- BB
4889    mov     r0, r0, lsr #8              @ r0<- CC
4890    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4891    GET_VREG(r2, r0)                    @ r2<- vCC
4892    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4893    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4894    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4895
4896    mov     r1, r1, asl r2              @  r1<- r1 << r2
4897    rsb     r3, r2, #32                 @  r3<- 32 - r2
4898    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4899    subs    ip, r2, #32                 @  ip<- r2 - 32
4900    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4901    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4902    b       .LOP_SHL_LONG_finish
4903
4904/* ------------------------------ */
4905    .balign 64
4906.L_OP_SHR_LONG: /* 0xa4 */
4907/* File: armv5te/OP_SHR_LONG.S */
4908    /*
4909     * Long integer shift.  This is different from the generic 32/64-bit
4910     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4911     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4912     * 6 bits of the shift distance.
4913     */
4914    /* shr-long vAA, vBB, vCC */
4915    FETCH(r0, 1)                        @ r0<- CCBB
4916    mov     r9, rINST, lsr #8           @ r9<- AA
4917    and     r3, r0, #255                @ r3<- BB
4918    mov     r0, r0, lsr #8              @ r0<- CC
4919    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4920    GET_VREG(r2, r0)                    @ r2<- vCC
4921    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4922    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4923    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4924
4925    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4926    rsb     r3, r2, #32                 @  r3<- 32 - r2
4927    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4928    subs    ip, r2, #32                 @  ip<- r2 - 32
4929    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4930    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4931    b       .LOP_SHR_LONG_finish
4932
4933/* ------------------------------ */
4934    .balign 64
4935.L_OP_USHR_LONG: /* 0xa5 */
4936/* File: armv5te/OP_USHR_LONG.S */
4937    /*
4938     * Long integer shift.  This is different from the generic 32/64-bit
4939     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4940     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4941     * 6 bits of the shift distance.
4942     */
4943    /* ushr-long vAA, vBB, vCC */
4944    FETCH(r0, 1)                        @ r0<- CCBB
4945    mov     r9, rINST, lsr #8           @ r9<- AA
4946    and     r3, r0, #255                @ r3<- BB
4947    mov     r0, r0, lsr #8              @ r0<- CC
4948    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4949    GET_VREG(r2, r0)                    @ r2<- vCC
4950    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4951    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4952    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4953
4954    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4955    rsb     r3, r2, #32                 @  r3<- 32 - r2
4956    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4957    subs    ip, r2, #32                 @  ip<- r2 - 32
4958    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4959    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4960    b       .LOP_USHR_LONG_finish
4961
4962/* ------------------------------ */
4963    .balign 64
4964.L_OP_ADD_FLOAT: /* 0xa6 */
4965/* File: arm-vfp/OP_ADD_FLOAT.S */
4966/* File: arm-vfp/fbinop.S */
4967    /*
4968     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4969     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4970     * use the "softfp" ABI, this must be an instruction, not a function call.
4971     *
4972     * For: add-float, sub-float, mul-float, div-float
4973     */
4974    /* floatop vAA, vBB, vCC */
4975    FETCH(r0, 1)                        @ r0<- CCBB
4976    mov     r9, rINST, lsr #8           @ r9<- AA
4977    mov     r3, r0, lsr #8              @ r3<- CC
4978    and     r2, r0, #255                @ r2<- BB
4979    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4980    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4981    flds    s1, [r3]                    @ s1<- vCC
4982    flds    s0, [r2]                    @ s0<- vBB
4983
4984    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4985    fadds   s2, s0, s1                              @ s2<- op
4986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4987    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4988    fsts    s2, [r9]                    @ vAA<- s2
4989    GOTO_OPCODE(ip)                     @ jump to next instruction
4990
4991
4992/* ------------------------------ */
4993    .balign 64
4994.L_OP_SUB_FLOAT: /* 0xa7 */
4995/* File: arm-vfp/OP_SUB_FLOAT.S */
4996/* File: arm-vfp/fbinop.S */
4997    /*
4998     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4999     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5000     * use the "softfp" ABI, this must be an instruction, not a function call.
5001     *
5002     * For: add-float, sub-float, mul-float, div-float
5003     */
5004    /* floatop vAA, vBB, vCC */
5005    FETCH(r0, 1)                        @ r0<- CCBB
5006    mov     r9, rINST, lsr #8           @ r9<- AA
5007    mov     r3, r0, lsr #8              @ r3<- CC
5008    and     r2, r0, #255                @ r2<- BB
5009    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5010    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5011    flds    s1, [r3]                    @ s1<- vCC
5012    flds    s0, [r2]                    @ s0<- vBB
5013
5014    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5015    fsubs   s2, s0, s1                              @ s2<- op
5016    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5017    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5018    fsts    s2, [r9]                    @ vAA<- s2
5019    GOTO_OPCODE(ip)                     @ jump to next instruction
5020
5021
5022/* ------------------------------ */
5023    .balign 64
5024.L_OP_MUL_FLOAT: /* 0xa8 */
5025/* File: arm-vfp/OP_MUL_FLOAT.S */
5026/* File: arm-vfp/fbinop.S */
5027    /*
5028     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5029     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5030     * use the "softfp" ABI, this must be an instruction, not a function call.
5031     *
5032     * For: add-float, sub-float, mul-float, div-float
5033     */
5034    /* floatop vAA, vBB, vCC */
5035    FETCH(r0, 1)                        @ r0<- CCBB
5036    mov     r9, rINST, lsr #8           @ r9<- AA
5037    mov     r3, r0, lsr #8              @ r3<- CC
5038    and     r2, r0, #255                @ r2<- BB
5039    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5040    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5041    flds    s1, [r3]                    @ s1<- vCC
5042    flds    s0, [r2]                    @ s0<- vBB
5043
5044    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5045    fmuls   s2, s0, s1                              @ s2<- op
5046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5047    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5048    fsts    s2, [r9]                    @ vAA<- s2
5049    GOTO_OPCODE(ip)                     @ jump to next instruction
5050
5051
5052/* ------------------------------ */
5053    .balign 64
5054.L_OP_DIV_FLOAT: /* 0xa9 */
5055/* File: arm-vfp/OP_DIV_FLOAT.S */
5056/* File: arm-vfp/fbinop.S */
5057    /*
5058     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5059     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5060     * use the "softfp" ABI, this must be an instruction, not a function call.
5061     *
5062     * For: add-float, sub-float, mul-float, div-float
5063     */
5064    /* floatop vAA, vBB, vCC */
5065    FETCH(r0, 1)                        @ r0<- CCBB
5066    mov     r9, rINST, lsr #8           @ r9<- AA
5067    mov     r3, r0, lsr #8              @ r3<- CC
5068    and     r2, r0, #255                @ r2<- BB
5069    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5070    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5071    flds    s1, [r3]                    @ s1<- vCC
5072    flds    s0, [r2]                    @ s0<- vBB
5073
5074    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5075    fdivs   s2, s0, s1                              @ s2<- op
5076    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5077    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5078    fsts    s2, [r9]                    @ vAA<- s2
5079    GOTO_OPCODE(ip)                     @ jump to next instruction
5080
5081
5082/* ------------------------------ */
5083    .balign 64
5084.L_OP_REM_FLOAT: /* 0xaa */
5085/* File: armv5te/OP_REM_FLOAT.S */
5086/* EABI doesn't define a float remainder function, but libm does */
5087/* File: armv5te/binop.S */
5088    /*
5089     * Generic 32-bit binary operation.  Provide an "instr" line that
5090     * specifies an instruction that performs "result = r0 op r1".
5091     * This could be an ARM instruction or a function call.  (If the result
5092     * comes back in a register other than r0, you can override "result".)
5093     *
5094     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5095     * vCC (r1).  Useful for integer division and modulus.  Note that we
5096     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5097     * handles it correctly.
5098     *
5099     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5100     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5101     *      mul-float, div-float, rem-float
5102     */
5103    /* binop vAA, vBB, vCC */
5104    FETCH(r0, 1)                        @ r0<- CCBB
5105    mov     r9, rINST, lsr #8           @ r9<- AA
5106    mov     r3, r0, lsr #8              @ r3<- CC
5107    and     r2, r0, #255                @ r2<- BB
5108    GET_VREG(r1, r3)                    @ r1<- vCC
5109    GET_VREG(r0, r2)                    @ r0<- vBB
5110    .if 0
5111    cmp     r1, #0                      @ is second operand zero?
5112    beq     common_errDivideByZero
5113    .endif
5114
5115    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5116                               @ optional op; may set condition codes
5117    bl      fmodf                              @ r0<- op, r0-r3 changed
5118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5119    SET_VREG(r0, r9)               @ vAA<- r0
5120    GOTO_OPCODE(ip)                     @ jump to next instruction
5121    /* 11-14 instructions */
5122
5123
5124
5125/* ------------------------------ */
5126    .balign 64
5127.L_OP_ADD_DOUBLE: /* 0xab */
5128/* File: arm-vfp/OP_ADD_DOUBLE.S */
5129/* File: arm-vfp/fbinopWide.S */
5130    /*
5131     * Generic 64-bit double-precision floating point binary operation.
5132     * Provide an "instr" line that specifies an instruction that performs
5133     * "d2 = d0 op d1".
5134     *
5135     * for: add-double, sub-double, mul-double, div-double
5136     */
5137    /* doubleop vAA, vBB, vCC */
5138    FETCH(r0, 1)                        @ r0<- CCBB
5139    mov     r9, rINST, lsr #8           @ r9<- AA
5140    mov     r3, r0, lsr #8              @ r3<- CC
5141    and     r2, r0, #255                @ r2<- BB
5142    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5143    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5144    fldd    d1, [r3]                    @ d1<- vCC
5145    fldd    d0, [r2]                    @ d0<- vBB
5146
5147    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5148    faddd   d2, d0, d1                              @ s2<- op
5149    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5150    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5151    fstd    d2, [r9]                    @ vAA<- d2
5152    GOTO_OPCODE(ip)                     @ jump to next instruction
5153
5154
5155/* ------------------------------ */
5156    .balign 64
5157.L_OP_SUB_DOUBLE: /* 0xac */
5158/* File: arm-vfp/OP_SUB_DOUBLE.S */
5159/* File: arm-vfp/fbinopWide.S */
5160    /*
5161     * Generic 64-bit double-precision floating point binary operation.
5162     * Provide an "instr" line that specifies an instruction that performs
5163     * "d2 = d0 op d1".
5164     *
5165     * for: add-double, sub-double, mul-double, div-double
5166     */
5167    /* doubleop vAA, vBB, vCC */
5168    FETCH(r0, 1)                        @ r0<- CCBB
5169    mov     r9, rINST, lsr #8           @ r9<- AA
5170    mov     r3, r0, lsr #8              @ r3<- CC
5171    and     r2, r0, #255                @ r2<- BB
5172    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5173    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5174    fldd    d1, [r3]                    @ d1<- vCC
5175    fldd    d0, [r2]                    @ d0<- vBB
5176
5177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5178    fsubd   d2, d0, d1                              @ s2<- op
5179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5180    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5181    fstd    d2, [r9]                    @ vAA<- d2
5182    GOTO_OPCODE(ip)                     @ jump to next instruction
5183
5184
5185/* ------------------------------ */
5186    .balign 64
5187.L_OP_MUL_DOUBLE: /* 0xad */
5188/* File: arm-vfp/OP_MUL_DOUBLE.S */
5189/* File: arm-vfp/fbinopWide.S */
5190    /*
5191     * Generic 64-bit double-precision floating point binary operation.
5192     * Provide an "instr" line that specifies an instruction that performs
5193     * "d2 = d0 op d1".
5194     *
5195     * for: add-double, sub-double, mul-double, div-double
5196     */
5197    /* doubleop vAA, vBB, vCC */
5198    FETCH(r0, 1)                        @ r0<- CCBB
5199    mov     r9, rINST, lsr #8           @ r9<- AA
5200    mov     r3, r0, lsr #8              @ r3<- CC
5201    and     r2, r0, #255                @ r2<- BB
5202    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5203    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5204    fldd    d1, [r3]                    @ d1<- vCC
5205    fldd    d0, [r2]                    @ d0<- vBB
5206
5207    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5208    fmuld   d2, d0, d1                              @ s2<- op
5209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5210    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5211    fstd    d2, [r9]                    @ vAA<- d2
5212    GOTO_OPCODE(ip)                     @ jump to next instruction
5213
5214
5215/* ------------------------------ */
5216    .balign 64
5217.L_OP_DIV_DOUBLE: /* 0xae */
5218/* File: arm-vfp/OP_DIV_DOUBLE.S */
5219/* File: arm-vfp/fbinopWide.S */
5220    /*
5221     * Generic 64-bit double-precision floating point binary operation.
5222     * Provide an "instr" line that specifies an instruction that performs
5223     * "d2 = d0 op d1".
5224     *
5225     * for: add-double, sub-double, mul-double, div-double
5226     */
5227    /* doubleop vAA, vBB, vCC */
5228    FETCH(r0, 1)                        @ r0<- CCBB
5229    mov     r9, rINST, lsr #8           @ r9<- AA
5230    mov     r3, r0, lsr #8              @ r3<- CC
5231    and     r2, r0, #255                @ r2<- BB
5232    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5233    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5234    fldd    d1, [r3]                    @ d1<- vCC
5235    fldd    d0, [r2]                    @ d0<- vBB
5236
5237    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5238    fdivd   d2, d0, d1                              @ s2<- op
5239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5240    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5241    fstd    d2, [r9]                    @ vAA<- d2
5242    GOTO_OPCODE(ip)                     @ jump to next instruction
5243
5244
5245/* ------------------------------ */
5246    .balign 64
5247.L_OP_REM_DOUBLE: /* 0xaf */
5248/* File: armv5te/OP_REM_DOUBLE.S */
5249/* EABI doesn't define a double remainder function, but libm does */
5250/* File: armv5te/binopWide.S */
5251    /*
5252     * Generic 64-bit binary operation.  Provide an "instr" line that
5253     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5254     * This could be an ARM instruction or a function call.  (If the result
5255     * comes back in a register other than r0, you can override "result".)
5256     *
5257     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5258     * vCC (r1).  Useful for integer division and modulus.
5259     *
5260     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5261     *      xor-long, add-double, sub-double, mul-double, div-double,
5262     *      rem-double
5263     *
5264     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5265     */
5266    /* binop vAA, vBB, vCC */
5267    FETCH(r0, 1)                        @ r0<- CCBB
5268    mov     r9, rINST, lsr #8           @ r9<- AA
5269    and     r2, r0, #255                @ r2<- BB
5270    mov     r3, r0, lsr #8              @ r3<- CC
5271    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5272    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5273    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5274    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5275    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5276    .if 0
5277    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5278    beq     common_errDivideByZero
5279    .endif
5280    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5281
5282                               @ optional op; may set condition codes
5283    bl      fmod                              @ result<- op, r0-r3 changed
5284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5285    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5286    GOTO_OPCODE(ip)                     @ jump to next instruction
5287    /* 14-17 instructions */
5288
5289
5290
5291/* ------------------------------ */
5292    .balign 64
5293.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5294/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5295/* File: armv6t2/binop2addr.S */
5296    /*
5297     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5298     * that specifies an instruction that performs "result = r0 op r1".
5299     * This could be an ARM instruction or a function call.  (If the result
5300     * comes back in a register other than r0, you can override "result".)
5301     *
5302     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5303     * vCC (r1).  Useful for integer division and modulus.
5304     *
5305     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5306     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5307     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5308     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5309     */
5310    /* binop/2addr vA, vB */
5311    mov     r3, rINST, lsr #12          @ r3<- B
5312    ubfx    r9, rINST, #8, #4           @ r9<- A
5313    GET_VREG(r1, r3)                    @ r1<- vB
5314    GET_VREG(r0, r9)                    @ r0<- vA
5315    .if 0
5316    cmp     r1, #0                      @ is second operand zero?
5317    beq     common_errDivideByZero
5318    .endif
5319    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5320
5321                               @ optional op; may set condition codes
5322    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5323    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5324    SET_VREG(r0, r9)               @ vAA<- r0
5325    GOTO_OPCODE(ip)                     @ jump to next instruction
5326    /* 10-13 instructions */
5327
5328
5329
5330/* ------------------------------ */
5331    .balign 64
5332.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5333/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5334/* File: armv6t2/binop2addr.S */
5335    /*
5336     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5337     * that specifies an instruction that performs "result = r0 op r1".
5338     * This could be an ARM instruction or a function call.  (If the result
5339     * comes back in a register other than r0, you can override "result".)
5340     *
5341     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5342     * vCC (r1).  Useful for integer division and modulus.
5343     *
5344     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5345     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5346     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5347     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5348     */
5349    /* binop/2addr vA, vB */
5350    mov     r3, rINST, lsr #12          @ r3<- B
5351    ubfx    r9, rINST, #8, #4           @ r9<- A
5352    GET_VREG(r1, r3)                    @ r1<- vB
5353    GET_VREG(r0, r9)                    @ r0<- vA
5354    .if 0
5355    cmp     r1, #0                      @ is second operand zero?
5356    beq     common_errDivideByZero
5357    .endif
5358    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5359
5360                               @ optional op; may set condition codes
5361    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5362    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5363    SET_VREG(r0, r9)               @ vAA<- r0
5364    GOTO_OPCODE(ip)                     @ jump to next instruction
5365    /* 10-13 instructions */
5366
5367
5368
5369/* ------------------------------ */
5370    .balign 64
5371.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5372/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5373/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5374/* File: armv6t2/binop2addr.S */
5375    /*
5376     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5377     * that specifies an instruction that performs "result = r0 op r1".
5378     * This could be an ARM instruction or a function call.  (If the result
5379     * comes back in a register other than r0, you can override "result".)
5380     *
5381     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5382     * vCC (r1).  Useful for integer division and modulus.
5383     *
5384     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5385     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5386     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5387     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5388     */
5389    /* binop/2addr vA, vB */
5390    mov     r3, rINST, lsr #12          @ r3<- B
5391    ubfx    r9, rINST, #8, #4           @ r9<- A
5392    GET_VREG(r1, r3)                    @ r1<- vB
5393    GET_VREG(r0, r9)                    @ r0<- vA
5394    .if 0
5395    cmp     r1, #0                      @ is second operand zero?
5396    beq     common_errDivideByZero
5397    .endif
5398    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5399
5400                               @ optional op; may set condition codes
5401    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5402    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5403    SET_VREG(r0, r9)               @ vAA<- r0
5404    GOTO_OPCODE(ip)                     @ jump to next instruction
5405    /* 10-13 instructions */
5406
5407
5408
5409/* ------------------------------ */
5410    .balign 64
5411.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5412/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5413/* File: armv6t2/binop2addr.S */
5414    /*
5415     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5416     * that specifies an instruction that performs "result = r0 op r1".
5417     * This could be an ARM instruction or a function call.  (If the result
5418     * comes back in a register other than r0, you can override "result".)
5419     *
5420     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5421     * vCC (r1).  Useful for integer division and modulus.
5422     *
5423     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5424     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5425     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5426     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5427     */
5428    /* binop/2addr vA, vB */
5429    mov     r3, rINST, lsr #12          @ r3<- B
5430    ubfx    r9, rINST, #8, #4           @ r9<- A
5431    GET_VREG(r1, r3)                    @ r1<- vB
5432    GET_VREG(r0, r9)                    @ r0<- vA
5433    .if 1
5434    cmp     r1, #0                      @ is second operand zero?
5435    beq     common_errDivideByZero
5436    .endif
5437    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5438
5439                               @ optional op; may set condition codes
5440    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5441    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5442    SET_VREG(r0, r9)               @ vAA<- r0
5443    GOTO_OPCODE(ip)                     @ jump to next instruction
5444    /* 10-13 instructions */
5445
5446
5447
5448/* ------------------------------ */
5449    .balign 64
5450.L_OP_REM_INT_2ADDR: /* 0xb4 */
5451/* File: armv6t2/OP_REM_INT_2ADDR.S */
5452/* idivmod returns quotient in r0 and remainder in r1 */
5453/* File: armv6t2/binop2addr.S */
5454    /*
5455     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5456     * that specifies an instruction that performs "result = r0 op r1".
5457     * This could be an ARM instruction or a function call.  (If the result
5458     * comes back in a register other than r0, you can override "result".)
5459     *
5460     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5461     * vCC (r1).  Useful for integer division and modulus.
5462     *
5463     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5464     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5465     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5466     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5467     */
5468    /* binop/2addr vA, vB */
5469    mov     r3, rINST, lsr #12          @ r3<- B
5470    ubfx    r9, rINST, #8, #4           @ r9<- A
5471    GET_VREG(r1, r3)                    @ r1<- vB
5472    GET_VREG(r0, r9)                    @ r0<- vA
5473    .if 1
5474    cmp     r1, #0                      @ is second operand zero?
5475    beq     common_errDivideByZero
5476    .endif
5477    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5478
5479                               @ optional op; may set condition codes
5480    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5482    SET_VREG(r1, r9)               @ vAA<- r1
5483    GOTO_OPCODE(ip)                     @ jump to next instruction
5484    /* 10-13 instructions */
5485
5486
5487
5488/* ------------------------------ */
5489    .balign 64
5490.L_OP_AND_INT_2ADDR: /* 0xb5 */
5491/* File: armv6t2/OP_AND_INT_2ADDR.S */
5492/* File: armv6t2/binop2addr.S */
5493    /*
5494     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5495     * that specifies an instruction that performs "result = r0 op r1".
5496     * This could be an ARM instruction or a function call.  (If the result
5497     * comes back in a register other than r0, you can override "result".)
5498     *
5499     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5500     * vCC (r1).  Useful for integer division and modulus.
5501     *
5502     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5503     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5504     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5505     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5506     */
5507    /* binop/2addr vA, vB */
5508    mov     r3, rINST, lsr #12          @ r3<- B
5509    ubfx    r9, rINST, #8, #4           @ r9<- A
5510    GET_VREG(r1, r3)                    @ r1<- vB
5511    GET_VREG(r0, r9)                    @ r0<- vA
5512    .if 0
5513    cmp     r1, #0                      @ is second operand zero?
5514    beq     common_errDivideByZero
5515    .endif
5516    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5517
5518                               @ optional op; may set condition codes
5519    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5521    SET_VREG(r0, r9)               @ vAA<- r0
5522    GOTO_OPCODE(ip)                     @ jump to next instruction
5523    /* 10-13 instructions */
5524
5525
5526
5527/* ------------------------------ */
5528    .balign 64
5529.L_OP_OR_INT_2ADDR: /* 0xb6 */
5530/* File: armv6t2/OP_OR_INT_2ADDR.S */
5531/* File: armv6t2/binop2addr.S */
5532    /*
5533     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5534     * that specifies an instruction that performs "result = r0 op r1".
5535     * This could be an ARM instruction or a function call.  (If the result
5536     * comes back in a register other than r0, you can override "result".)
5537     *
5538     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5539     * vCC (r1).  Useful for integer division and modulus.
5540     *
5541     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5542     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5543     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5544     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5545     */
5546    /* binop/2addr vA, vB */
5547    mov     r3, rINST, lsr #12          @ r3<- B
5548    ubfx    r9, rINST, #8, #4           @ r9<- A
5549    GET_VREG(r1, r3)                    @ r1<- vB
5550    GET_VREG(r0, r9)                    @ r0<- vA
5551    .if 0
5552    cmp     r1, #0                      @ is second operand zero?
5553    beq     common_errDivideByZero
5554    .endif
5555    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5556
5557                               @ optional op; may set condition codes
5558    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5559    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5560    SET_VREG(r0, r9)               @ vAA<- r0
5561    GOTO_OPCODE(ip)                     @ jump to next instruction
5562    /* 10-13 instructions */
5563
5564
5565
5566/* ------------------------------ */
5567    .balign 64
5568.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5569/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5570/* File: armv6t2/binop2addr.S */
5571    /*
5572     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5573     * that specifies an instruction that performs "result = r0 op r1".
5574     * This could be an ARM instruction or a function call.  (If the result
5575     * comes back in a register other than r0, you can override "result".)
5576     *
5577     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5578     * vCC (r1).  Useful for integer division and modulus.
5579     *
5580     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5581     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5582     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5583     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5584     */
5585    /* binop/2addr vA, vB */
5586    mov     r3, rINST, lsr #12          @ r3<- B
5587    ubfx    r9, rINST, #8, #4           @ r9<- A
5588    GET_VREG(r1, r3)                    @ r1<- vB
5589    GET_VREG(r0, r9)                    @ r0<- vA
5590    .if 0
5591    cmp     r1, #0                      @ is second operand zero?
5592    beq     common_errDivideByZero
5593    .endif
5594    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5595
5596                               @ optional op; may set condition codes
5597    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5598    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5599    SET_VREG(r0, r9)               @ vAA<- r0
5600    GOTO_OPCODE(ip)                     @ jump to next instruction
5601    /* 10-13 instructions */
5602
5603
5604
5605/* ------------------------------ */
5606    .balign 64
5607.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5608/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5609/* File: armv6t2/binop2addr.S */
5610    /*
5611     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5612     * that specifies an instruction that performs "result = r0 op r1".
5613     * This could be an ARM instruction or a function call.  (If the result
5614     * comes back in a register other than r0, you can override "result".)
5615     *
5616     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5617     * vCC (r1).  Useful for integer division and modulus.
5618     *
5619     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5620     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5621     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5622     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5623     */
5624    /* binop/2addr vA, vB */
5625    mov     r3, rINST, lsr #12          @ r3<- B
5626    ubfx    r9, rINST, #8, #4           @ r9<- A
5627    GET_VREG(r1, r3)                    @ r1<- vB
5628    GET_VREG(r0, r9)                    @ r0<- vA
5629    .if 0
5630    cmp     r1, #0                      @ is second operand zero?
5631    beq     common_errDivideByZero
5632    .endif
5633    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5634
5635    and     r1, r1, #31                           @ optional op; may set condition codes
5636    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5638    SET_VREG(r0, r9)               @ vAA<- r0
5639    GOTO_OPCODE(ip)                     @ jump to next instruction
5640    /* 10-13 instructions */
5641
5642
5643
5644/* ------------------------------ */
5645    .balign 64
5646.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5647/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5648/* File: armv6t2/binop2addr.S */
5649    /*
5650     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5651     * that specifies an instruction that performs "result = r0 op r1".
5652     * This could be an ARM instruction or a function call.  (If the result
5653     * comes back in a register other than r0, you can override "result".)
5654     *
5655     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5656     * vCC (r1).  Useful for integer division and modulus.
5657     *
5658     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5659     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5660     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5661     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5662     */
5663    /* binop/2addr vA, vB */
5664    mov     r3, rINST, lsr #12          @ r3<- B
5665    ubfx    r9, rINST, #8, #4           @ r9<- A
5666    GET_VREG(r1, r3)                    @ r1<- vB
5667    GET_VREG(r0, r9)                    @ r0<- vA
5668    .if 0
5669    cmp     r1, #0                      @ is second operand zero?
5670    beq     common_errDivideByZero
5671    .endif
5672    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5673
5674    and     r1, r1, #31                           @ optional op; may set condition codes
5675    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5677    SET_VREG(r0, r9)               @ vAA<- r0
5678    GOTO_OPCODE(ip)                     @ jump to next instruction
5679    /* 10-13 instructions */
5680
5681
5682
5683/* ------------------------------ */
5684    .balign 64
5685.L_OP_USHR_INT_2ADDR: /* 0xba */
5686/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5687/* File: armv6t2/binop2addr.S */
5688    /*
5689     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5690     * that specifies an instruction that performs "result = r0 op r1".
5691     * This could be an ARM instruction or a function call.  (If the result
5692     * comes back in a register other than r0, you can override "result".)
5693     *
5694     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5695     * vCC (r1).  Useful for integer division and modulus.
5696     *
5697     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5698     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5699     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5700     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5701     */
5702    /* binop/2addr vA, vB */
5703    mov     r3, rINST, lsr #12          @ r3<- B
5704    ubfx    r9, rINST, #8, #4           @ r9<- A
5705    GET_VREG(r1, r3)                    @ r1<- vB
5706    GET_VREG(r0, r9)                    @ r0<- vA
5707    .if 0
5708    cmp     r1, #0                      @ is second operand zero?
5709    beq     common_errDivideByZero
5710    .endif
5711    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5712
5713    and     r1, r1, #31                           @ optional op; may set condition codes
5714    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5716    SET_VREG(r0, r9)               @ vAA<- r0
5717    GOTO_OPCODE(ip)                     @ jump to next instruction
5718    /* 10-13 instructions */
5719
5720
5721
5722/* ------------------------------ */
5723    .balign 64
5724.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5725/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5726/* File: armv6t2/binopWide2addr.S */
5727    /*
5728     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5729     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5730     * This could be an ARM instruction or a function call.  (If the result
5731     * comes back in a register other than r0, you can override "result".)
5732     *
5733     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5734     * vCC (r1).  Useful for integer division and modulus.
5735     *
5736     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5737     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5738     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5739     *      rem-double/2addr
5740     */
5741    /* binop/2addr vA, vB */
5742    mov     r1, rINST, lsr #12          @ r1<- B
5743    ubfx    r9, rINST, #8, #4           @ r9<- A
5744    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5745    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5746    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5747    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5748    .if 0
5749    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5750    beq     common_errDivideByZero
5751    .endif
5752    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5753
5754    adds    r0, r0, r2                           @ optional op; may set condition codes
5755    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5757    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5758    GOTO_OPCODE(ip)                     @ jump to next instruction
5759    /* 12-15 instructions */
5760
5761
5762
5763/* ------------------------------ */
5764    .balign 64
5765.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5766/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5767/* File: armv6t2/binopWide2addr.S */
5768    /*
5769     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5770     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5771     * This could be an ARM instruction or a function call.  (If the result
5772     * comes back in a register other than r0, you can override "result".)
5773     *
5774     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5775     * vCC (r1).  Useful for integer division and modulus.
5776     *
5777     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5778     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5779     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5780     *      rem-double/2addr
5781     */
5782    /* binop/2addr vA, vB */
5783    mov     r1, rINST, lsr #12          @ r1<- B
5784    ubfx    r9, rINST, #8, #4           @ r9<- A
5785    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5786    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5787    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5788    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5789    .if 0
5790    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5791    beq     common_errDivideByZero
5792    .endif
5793    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5794
5795    subs    r0, r0, r2                           @ optional op; may set condition codes
5796    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5797    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5798    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5799    GOTO_OPCODE(ip)                     @ jump to next instruction
5800    /* 12-15 instructions */
5801
5802
5803
5804/* ------------------------------ */
5805    .balign 64
5806.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5807/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5808    /*
5809     * Signed 64-bit integer multiply, "/2addr" version.
5810     *
5811     * See OP_MUL_LONG for an explanation.
5812     *
5813     * We get a little tight on registers, so to avoid looking up &fp[A]
5814     * again we stuff it into rINST.
5815     */
5816    /* mul-long/2addr vA, vB */
5817    mov     r1, rINST, lsr #12          @ r1<- B
5818    ubfx    r9, rINST, #8, #4           @ r9<- A
5819    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5820    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5821    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5822    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5823    mul     ip, r2, r1                  @  ip<- ZxW
5824    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5825    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5826    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5827    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5828    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5830    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5831    GOTO_OPCODE(ip)                     @ jump to next instruction
5832
5833
5834/* ------------------------------ */
5835    .balign 64
5836.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5837/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5838/* File: armv6t2/binopWide2addr.S */
5839    /*
5840     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5841     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5842     * This could be an ARM instruction or a function call.  (If the result
5843     * comes back in a register other than r0, you can override "result".)
5844     *
5845     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5846     * vCC (r1).  Useful for integer division and modulus.
5847     *
5848     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5849     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5850     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5851     *      rem-double/2addr
5852     */
5853    /* binop/2addr vA, vB */
5854    mov     r1, rINST, lsr #12          @ r1<- B
5855    ubfx    r9, rINST, #8, #4           @ r9<- A
5856    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5857    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5858    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5859    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5860    .if 1
5861    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5862    beq     common_errDivideByZero
5863    .endif
5864    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5865
5866                               @ optional op; may set condition codes
5867    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5869    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5870    GOTO_OPCODE(ip)                     @ jump to next instruction
5871    /* 12-15 instructions */
5872
5873
5874
5875/* ------------------------------ */
5876    .balign 64
5877.L_OP_REM_LONG_2ADDR: /* 0xbf */
5878/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5879/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5880/* File: armv6t2/binopWide2addr.S */
5881    /*
5882     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5883     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5884     * This could be an ARM instruction or a function call.  (If the result
5885     * comes back in a register other than r0, you can override "result".)
5886     *
5887     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5888     * vCC (r1).  Useful for integer division and modulus.
5889     *
5890     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5891     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5892     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5893     *      rem-double/2addr
5894     */
5895    /* binop/2addr vA, vB */
5896    mov     r1, rINST, lsr #12          @ r1<- B
5897    ubfx    r9, rINST, #8, #4           @ r9<- A
5898    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5900    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5901    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5902    .if 1
5903    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5904    beq     common_errDivideByZero
5905    .endif
5906    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5907
5908                               @ optional op; may set condition codes
5909    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5911    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5912    GOTO_OPCODE(ip)                     @ jump to next instruction
5913    /* 12-15 instructions */
5914
5915
5916
5917/* ------------------------------ */
5918    .balign 64
5919.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5920/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5921/* File: armv6t2/binopWide2addr.S */
5922    /*
5923     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5924     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5925     * This could be an ARM instruction or a function call.  (If the result
5926     * comes back in a register other than r0, you can override "result".)
5927     *
5928     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5929     * vCC (r1).  Useful for integer division and modulus.
5930     *
5931     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5932     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5933     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5934     *      rem-double/2addr
5935     */
5936    /* binop/2addr vA, vB */
5937    mov     r1, rINST, lsr #12          @ r1<- B
5938    ubfx    r9, rINST, #8, #4           @ r9<- A
5939    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5940    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5941    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5942    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5943    .if 0
5944    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5945    beq     common_errDivideByZero
5946    .endif
5947    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5948
5949    and     r0, r0, r2                           @ optional op; may set condition codes
5950    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5952    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5953    GOTO_OPCODE(ip)                     @ jump to next instruction
5954    /* 12-15 instructions */
5955
5956
5957
5958/* ------------------------------ */
5959    .balign 64
5960.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5961/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5962/* File: armv6t2/binopWide2addr.S */
5963    /*
5964     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5965     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5966     * This could be an ARM instruction or a function call.  (If the result
5967     * comes back in a register other than r0, you can override "result".)
5968     *
5969     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5970     * vCC (r1).  Useful for integer division and modulus.
5971     *
5972     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5973     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5974     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5975     *      rem-double/2addr
5976     */
5977    /* binop/2addr vA, vB */
5978    mov     r1, rINST, lsr #12          @ r1<- B
5979    ubfx    r9, rINST, #8, #4           @ r9<- A
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    orr     r0, r0, r2                           @ optional op; may set condition codes
5991    orr     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_XOR_LONG_2ADDR: /* 0xc2 */
6002/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
6003/* File: armv6t2/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     r1, rINST, lsr #12          @ r1<- B
6020    ubfx    r9, rINST, #8, #4           @ r9<- A
6021    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6022    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6023    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6024    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6025    .if 0
6026    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6027    beq     common_errDivideByZero
6028    .endif
6029    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6030
6031    eor     r0, r0, r2                           @ optional op; may set condition codes
6032    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6033    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6034    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6035    GOTO_OPCODE(ip)                     @ jump to next instruction
6036    /* 12-15 instructions */
6037
6038
6039
6040/* ------------------------------ */
6041    .balign 64
6042.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6043/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6044    /*
6045     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6046     * 32-bit shift distance.
6047     */
6048    /* shl-long/2addr vA, vB */
6049    mov     r3, rINST, lsr #12          @ r3<- B
6050    ubfx    r9, rINST, #8, #4           @ r9<- A
6051    GET_VREG(r2, r3)                    @ r2<- vB
6052    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6053    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6054    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6055
6056    mov     r1, r1, asl r2              @  r1<- r1 << r2
6057    rsb     r3, r2, #32                 @  r3<- 32 - r2
6058    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6059    subs    ip, r2, #32                 @  ip<- r2 - 32
6060    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6061    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6062    mov     r0, r0, asl r2              @  r0<- r0 << r2
6063    b       .LOP_SHL_LONG_2ADDR_finish
6064
6065/* ------------------------------ */
6066    .balign 64
6067.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6068/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6069    /*
6070     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6071     * 32-bit shift distance.
6072     */
6073    /* shr-long/2addr vA, vB */
6074    mov     r3, rINST, lsr #12          @ r3<- B
6075    ubfx    r9, rINST, #8, #4           @ r9<- A
6076    GET_VREG(r2, r3)                    @ r2<- vB
6077    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6078    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6079    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6080
6081    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6082    rsb     r3, r2, #32                 @  r3<- 32 - r2
6083    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6084    subs    ip, r2, #32                 @  ip<- r2 - 32
6085    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6086    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6087    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6088    b       .LOP_SHR_LONG_2ADDR_finish
6089
6090/* ------------------------------ */
6091    .balign 64
6092.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6093/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6094    /*
6095     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6096     * 32-bit shift distance.
6097     */
6098    /* ushr-long/2addr vA, vB */
6099    mov     r3, rINST, lsr #12          @ r3<- B
6100    ubfx    r9, rINST, #8, #4           @ r9<- A
6101    GET_VREG(r2, r3)                    @ r2<- vB
6102    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6103    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6104    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6105
6106    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6107    rsb     r3, r2, #32                 @  r3<- 32 - r2
6108    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6109    subs    ip, r2, #32                 @  ip<- r2 - 32
6110    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6111    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6112    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6113    b       .LOP_USHR_LONG_2ADDR_finish
6114
6115/* ------------------------------ */
6116    .balign 64
6117.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6118/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6119/* File: arm-vfp/fbinop2addr.S */
6120    /*
6121     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6122     * an "instr" line that specifies an instruction that performs
6123     * "s2 = s0 op s1".
6124     *
6125     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6126     */
6127    /* binop/2addr vA, vB */
6128    mov     r3, rINST, lsr #12          @ r3<- B
6129    mov     r9, rINST, lsr #8           @ r9<- A+
6130    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6131    and     r9, r9, #15                 @ r9<- A
6132    flds    s1, [r3]                    @ s1<- vB
6133    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6134    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6135    flds    s0, [r9]                    @ s0<- vA
6136
6137    fadds   s2, s0, s1                              @ s2<- op
6138    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6139    fsts    s2, [r9]                    @ vAA<- s2
6140    GOTO_OPCODE(ip)                     @ jump to next instruction
6141
6142
6143/* ------------------------------ */
6144    .balign 64
6145.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6146/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6147/* File: arm-vfp/fbinop2addr.S */
6148    /*
6149     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6150     * an "instr" line that specifies an instruction that performs
6151     * "s2 = s0 op s1".
6152     *
6153     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6154     */
6155    /* binop/2addr vA, vB */
6156    mov     r3, rINST, lsr #12          @ r3<- B
6157    mov     r9, rINST, lsr #8           @ r9<- A+
6158    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6159    and     r9, r9, #15                 @ r9<- A
6160    flds    s1, [r3]                    @ s1<- vB
6161    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6162    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6163    flds    s0, [r9]                    @ s0<- vA
6164
6165    fsubs   s2, s0, s1                              @ s2<- op
6166    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6167    fsts    s2, [r9]                    @ vAA<- s2
6168    GOTO_OPCODE(ip)                     @ jump to next instruction
6169
6170
6171/* ------------------------------ */
6172    .balign 64
6173.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6174/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6175/* File: arm-vfp/fbinop2addr.S */
6176    /*
6177     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6178     * an "instr" line that specifies an instruction that performs
6179     * "s2 = s0 op s1".
6180     *
6181     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6182     */
6183    /* binop/2addr vA, vB */
6184    mov     r3, rINST, lsr #12          @ r3<- B
6185    mov     r9, rINST, lsr #8           @ r9<- A+
6186    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6187    and     r9, r9, #15                 @ r9<- A
6188    flds    s1, [r3]                    @ s1<- vB
6189    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6190    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6191    flds    s0, [r9]                    @ s0<- vA
6192
6193    fmuls   s2, s0, s1                              @ s2<- op
6194    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6195    fsts    s2, [r9]                    @ vAA<- s2
6196    GOTO_OPCODE(ip)                     @ jump to next instruction
6197
6198
6199/* ------------------------------ */
6200    .balign 64
6201.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6202/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6203/* File: arm-vfp/fbinop2addr.S */
6204    /*
6205     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6206     * an "instr" line that specifies an instruction that performs
6207     * "s2 = s0 op s1".
6208     *
6209     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6210     */
6211    /* binop/2addr vA, vB */
6212    mov     r3, rINST, lsr #12          @ r3<- B
6213    mov     r9, rINST, lsr #8           @ r9<- A+
6214    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6215    and     r9, r9, #15                 @ r9<- A
6216    flds    s1, [r3]                    @ s1<- vB
6217    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6218    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6219    flds    s0, [r9]                    @ s0<- vA
6220
6221    fdivs   s2, s0, s1                              @ s2<- op
6222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6223    fsts    s2, [r9]                    @ vAA<- s2
6224    GOTO_OPCODE(ip)                     @ jump to next instruction
6225
6226
6227/* ------------------------------ */
6228    .balign 64
6229.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6230/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6231/* EABI doesn't define a float remainder function, but libm does */
6232/* File: armv6t2/binop2addr.S */
6233    /*
6234     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6235     * that specifies an instruction that performs "result = r0 op r1".
6236     * This could be an ARM instruction or a function call.  (If the result
6237     * comes back in a register other than r0, you can override "result".)
6238     *
6239     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6240     * vCC (r1).  Useful for integer division and modulus.
6241     *
6242     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6243     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6244     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6245     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6246     */
6247    /* binop/2addr vA, vB */
6248    mov     r3, rINST, lsr #12          @ r3<- B
6249    ubfx    r9, rINST, #8, #4           @ r9<- A
6250    GET_VREG(r1, r3)                    @ r1<- vB
6251    GET_VREG(r0, r9)                    @ r0<- vA
6252    .if 0
6253    cmp     r1, #0                      @ is second operand zero?
6254    beq     common_errDivideByZero
6255    .endif
6256    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6257
6258                               @ optional op; may set condition codes
6259    bl      fmodf                              @ r0<- op, r0-r3 changed
6260    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6261    SET_VREG(r0, r9)               @ vAA<- r0
6262    GOTO_OPCODE(ip)                     @ jump to next instruction
6263    /* 10-13 instructions */
6264
6265
6266
6267/* ------------------------------ */
6268    .balign 64
6269.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6270/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6271/* File: arm-vfp/fbinopWide2addr.S */
6272    /*
6273     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6274     * an "instr" line that specifies an instruction that performs
6275     * "d2 = d0 op d1".
6276     *
6277     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6278     *      div-double/2addr
6279     */
6280    /* binop/2addr vA, vB */
6281    mov     r3, rINST, lsr #12          @ r3<- B
6282    mov     r9, rINST, lsr #8           @ r9<- A+
6283    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6284    and     r9, r9, #15                 @ r9<- A
6285    fldd    d1, [r3]                    @ d1<- vB
6286    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6287    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6288    fldd    d0, [r9]                    @ d0<- vA
6289
6290    faddd   d2, d0, d1                              @ d2<- op
6291    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6292    fstd    d2, [r9]                    @ vAA<- d2
6293    GOTO_OPCODE(ip)                     @ jump to next instruction
6294
6295
6296/* ------------------------------ */
6297    .balign 64
6298.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6299/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6300/* File: arm-vfp/fbinopWide2addr.S */
6301    /*
6302     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6303     * an "instr" line that specifies an instruction that performs
6304     * "d2 = d0 op d1".
6305     *
6306     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6307     *      div-double/2addr
6308     */
6309    /* binop/2addr vA, vB */
6310    mov     r3, rINST, lsr #12          @ r3<- B
6311    mov     r9, rINST, lsr #8           @ r9<- A+
6312    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6313    and     r9, r9, #15                 @ r9<- A
6314    fldd    d1, [r3]                    @ d1<- vB
6315    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6316    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6317    fldd    d0, [r9]                    @ d0<- vA
6318
6319    fsubd   d2, d0, d1                              @ d2<- op
6320    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6321    fstd    d2, [r9]                    @ vAA<- d2
6322    GOTO_OPCODE(ip)                     @ jump to next instruction
6323
6324
6325/* ------------------------------ */
6326    .balign 64
6327.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6328/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6329/* File: arm-vfp/fbinopWide2addr.S */
6330    /*
6331     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6332     * an "instr" line that specifies an instruction that performs
6333     * "d2 = d0 op d1".
6334     *
6335     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6336     *      div-double/2addr
6337     */
6338    /* binop/2addr vA, vB */
6339    mov     r3, rINST, lsr #12          @ r3<- B
6340    mov     r9, rINST, lsr #8           @ r9<- A+
6341    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6342    and     r9, r9, #15                 @ r9<- A
6343    fldd    d1, [r3]                    @ d1<- vB
6344    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6345    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6346    fldd    d0, [r9]                    @ d0<- vA
6347
6348    fmuld   d2, d0, d1                              @ d2<- op
6349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6350    fstd    d2, [r9]                    @ vAA<- d2
6351    GOTO_OPCODE(ip)                     @ jump to next instruction
6352
6353
6354/* ------------------------------ */
6355    .balign 64
6356.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6357/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6358/* File: arm-vfp/fbinopWide2addr.S */
6359    /*
6360     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6361     * an "instr" line that specifies an instruction that performs
6362     * "d2 = d0 op d1".
6363     *
6364     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6365     *      div-double/2addr
6366     */
6367    /* binop/2addr vA, vB */
6368    mov     r3, rINST, lsr #12          @ r3<- B
6369    mov     r9, rINST, lsr #8           @ r9<- A+
6370    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6371    and     r9, r9, #15                 @ r9<- A
6372    fldd    d1, [r3]                    @ d1<- vB
6373    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6374    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6375    fldd    d0, [r9]                    @ d0<- vA
6376
6377    fdivd   d2, d0, d1                              @ d2<- op
6378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6379    fstd    d2, [r9]                    @ vAA<- d2
6380    GOTO_OPCODE(ip)                     @ jump to next instruction
6381
6382
6383/* ------------------------------ */
6384    .balign 64
6385.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6386/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6387/* EABI doesn't define a double remainder function, but libm does */
6388/* File: armv6t2/binopWide2addr.S */
6389    /*
6390     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6391     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6392     * This could be an ARM instruction or a function call.  (If the result
6393     * comes back in a register other than r0, you can override "result".)
6394     *
6395     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6396     * vCC (r1).  Useful for integer division and modulus.
6397     *
6398     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6399     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6400     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6401     *      rem-double/2addr
6402     */
6403    /* binop/2addr vA, vB */
6404    mov     r1, rINST, lsr #12          @ r1<- B
6405    ubfx    r9, rINST, #8, #4           @ r9<- A
6406    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6407    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6408    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6409    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6410    .if 0
6411    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6412    beq     common_errDivideByZero
6413    .endif
6414    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6415
6416                               @ optional op; may set condition codes
6417    bl      fmod                              @ result<- op, r0-r3 changed
6418    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6419    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6420    GOTO_OPCODE(ip)                     @ jump to next instruction
6421    /* 12-15 instructions */
6422
6423
6424
6425/* ------------------------------ */
6426    .balign 64
6427.L_OP_ADD_INT_LIT16: /* 0xd0 */
6428/* File: armv6t2/OP_ADD_INT_LIT16.S */
6429/* File: armv6t2/binopLit16.S */
6430    /*
6431     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6432     * that specifies an instruction that performs "result = r0 op r1".
6433     * This could be an ARM instruction or a function call.  (If the result
6434     * comes back in a register other than r0, you can override "result".)
6435     *
6436     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6437     * vCC (r1).  Useful for integer division and modulus.
6438     *
6439     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6440     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6441     */
6442    /* binop/lit16 vA, vB, #+CCCC */
6443    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6444    mov     r2, rINST, lsr #12          @ r2<- B
6445    ubfx    r9, rINST, #8, #4           @ r9<- A
6446    GET_VREG(r0, r2)                    @ r0<- vB
6447    .if 0
6448    cmp     r1, #0                      @ is second operand zero?
6449    beq     common_errDivideByZero
6450    .endif
6451    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6452
6453    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6455    SET_VREG(r0, r9)               @ vAA<- r0
6456    GOTO_OPCODE(ip)                     @ jump to next instruction
6457    /* 10-13 instructions */
6458
6459
6460
6461/* ------------------------------ */
6462    .balign 64
6463.L_OP_RSUB_INT: /* 0xd1 */
6464/* File: armv6t2/OP_RSUB_INT.S */
6465/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6466/* File: armv6t2/binopLit16.S */
6467    /*
6468     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6469     * that specifies an instruction that performs "result = r0 op r1".
6470     * This could be an ARM instruction or a function call.  (If the result
6471     * comes back in a register other than r0, you can override "result".)
6472     *
6473     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6474     * vCC (r1).  Useful for integer division and modulus.
6475     *
6476     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6477     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6478     */
6479    /* binop/lit16 vA, vB, #+CCCC */
6480    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6481    mov     r2, rINST, lsr #12          @ r2<- B
6482    ubfx    r9, rINST, #8, #4           @ r9<- A
6483    GET_VREG(r0, r2)                    @ r0<- vB
6484    .if 0
6485    cmp     r1, #0                      @ is second operand zero?
6486    beq     common_errDivideByZero
6487    .endif
6488    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6489
6490    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6492    SET_VREG(r0, r9)               @ vAA<- r0
6493    GOTO_OPCODE(ip)                     @ jump to next instruction
6494    /* 10-13 instructions */
6495
6496
6497
6498/* ------------------------------ */
6499    .balign 64
6500.L_OP_MUL_INT_LIT16: /* 0xd2 */
6501/* File: armv6t2/OP_MUL_INT_LIT16.S */
6502/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6503/* File: armv6t2/binopLit16.S */
6504    /*
6505     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6506     * that specifies an instruction that performs "result = r0 op r1".
6507     * This could be an ARM instruction or a function call.  (If the result
6508     * comes back in a register other than r0, you can override "result".)
6509     *
6510     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6511     * vCC (r1).  Useful for integer division and modulus.
6512     *
6513     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6514     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6515     */
6516    /* binop/lit16 vA, vB, #+CCCC */
6517    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6518    mov     r2, rINST, lsr #12          @ r2<- B
6519    ubfx    r9, rINST, #8, #4           @ r9<- A
6520    GET_VREG(r0, r2)                    @ r0<- vB
6521    .if 0
6522    cmp     r1, #0                      @ is second operand zero?
6523    beq     common_errDivideByZero
6524    .endif
6525    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6526
6527    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6528    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6529    SET_VREG(r0, r9)               @ vAA<- r0
6530    GOTO_OPCODE(ip)                     @ jump to next instruction
6531    /* 10-13 instructions */
6532
6533
6534
6535/* ------------------------------ */
6536    .balign 64
6537.L_OP_DIV_INT_LIT16: /* 0xd3 */
6538/* File: armv6t2/OP_DIV_INT_LIT16.S */
6539/* File: armv6t2/binopLit16.S */
6540    /*
6541     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6542     * that specifies an instruction that performs "result = r0 op r1".
6543     * This could be an ARM instruction or a function call.  (If the result
6544     * comes back in a register other than r0, you can override "result".)
6545     *
6546     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6547     * vCC (r1).  Useful for integer division and modulus.
6548     *
6549     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6550     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6551     */
6552    /* binop/lit16 vA, vB, #+CCCC */
6553    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6554    mov     r2, rINST, lsr #12          @ r2<- B
6555    ubfx    r9, rINST, #8, #4           @ r9<- A
6556    GET_VREG(r0, r2)                    @ r0<- vB
6557    .if 1
6558    cmp     r1, #0                      @ is second operand zero?
6559    beq     common_errDivideByZero
6560    .endif
6561    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6562
6563    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6565    SET_VREG(r0, r9)               @ vAA<- r0
6566    GOTO_OPCODE(ip)                     @ jump to next instruction
6567    /* 10-13 instructions */
6568
6569
6570
6571/* ------------------------------ */
6572    .balign 64
6573.L_OP_REM_INT_LIT16: /* 0xd4 */
6574/* File: armv6t2/OP_REM_INT_LIT16.S */
6575/* idivmod returns quotient in r0 and remainder in r1 */
6576/* File: armv6t2/binopLit16.S */
6577    /*
6578     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6579     * that specifies an instruction that performs "result = r0 op r1".
6580     * This could be an ARM instruction or a function call.  (If the result
6581     * comes back in a register other than r0, you can override "result".)
6582     *
6583     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6584     * vCC (r1).  Useful for integer division and modulus.
6585     *
6586     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6587     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6588     */
6589    /* binop/lit16 vA, vB, #+CCCC */
6590    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6591    mov     r2, rINST, lsr #12          @ r2<- B
6592    ubfx    r9, rINST, #8, #4           @ r9<- A
6593    GET_VREG(r0, r2)                    @ r0<- vB
6594    .if 1
6595    cmp     r1, #0                      @ is second operand zero?
6596    beq     common_errDivideByZero
6597    .endif
6598    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6599
6600    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6601    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6602    SET_VREG(r1, r9)               @ vAA<- r1
6603    GOTO_OPCODE(ip)                     @ jump to next instruction
6604    /* 10-13 instructions */
6605
6606
6607
6608/* ------------------------------ */
6609    .balign 64
6610.L_OP_AND_INT_LIT16: /* 0xd5 */
6611/* File: armv6t2/OP_AND_INT_LIT16.S */
6612/* File: armv6t2/binopLit16.S */
6613    /*
6614     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6615     * that specifies an instruction that performs "result = r0 op r1".
6616     * This could be an ARM instruction or a function call.  (If the result
6617     * comes back in a register other than r0, you can override "result".)
6618     *
6619     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6620     * vCC (r1).  Useful for integer division and modulus.
6621     *
6622     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6623     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6624     */
6625    /* binop/lit16 vA, vB, #+CCCC */
6626    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6627    mov     r2, rINST, lsr #12          @ r2<- B
6628    ubfx    r9, rINST, #8, #4           @ r9<- A
6629    GET_VREG(r0, r2)                    @ r0<- vB
6630    .if 0
6631    cmp     r1, #0                      @ is second operand zero?
6632    beq     common_errDivideByZero
6633    .endif
6634    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6635
6636    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6638    SET_VREG(r0, r9)               @ vAA<- r0
6639    GOTO_OPCODE(ip)                     @ jump to next instruction
6640    /* 10-13 instructions */
6641
6642
6643
6644/* ------------------------------ */
6645    .balign 64
6646.L_OP_OR_INT_LIT16: /* 0xd6 */
6647/* File: armv6t2/OP_OR_INT_LIT16.S */
6648/* File: armv6t2/binopLit16.S */
6649    /*
6650     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6651     * that specifies an instruction that performs "result = r0 op r1".
6652     * This could be an ARM instruction or a function call.  (If the result
6653     * comes back in a register other than r0, you can override "result".)
6654     *
6655     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6656     * vCC (r1).  Useful for integer division and modulus.
6657     *
6658     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6659     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6660     */
6661    /* binop/lit16 vA, vB, #+CCCC */
6662    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6663    mov     r2, rINST, lsr #12          @ r2<- B
6664    ubfx    r9, rINST, #8, #4           @ r9<- A
6665    GET_VREG(r0, r2)                    @ r0<- vB
6666    .if 0
6667    cmp     r1, #0                      @ is second operand zero?
6668    beq     common_errDivideByZero
6669    .endif
6670    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6671
6672    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6674    SET_VREG(r0, r9)               @ vAA<- r0
6675    GOTO_OPCODE(ip)                     @ jump to next instruction
6676    /* 10-13 instructions */
6677
6678
6679
6680/* ------------------------------ */
6681    .balign 64
6682.L_OP_XOR_INT_LIT16: /* 0xd7 */
6683/* File: armv6t2/OP_XOR_INT_LIT16.S */
6684/* File: armv6t2/binopLit16.S */
6685    /*
6686     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6687     * that specifies an instruction that performs "result = r0 op r1".
6688     * This could be an ARM instruction or a function call.  (If the result
6689     * comes back in a register other than r0, you can override "result".)
6690     *
6691     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6692     * vCC (r1).  Useful for integer division and modulus.
6693     *
6694     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6695     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6696     */
6697    /* binop/lit16 vA, vB, #+CCCC */
6698    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6699    mov     r2, rINST, lsr #12          @ r2<- B
6700    ubfx    r9, rINST, #8, #4           @ r9<- A
6701    GET_VREG(r0, r2)                    @ r0<- vB
6702    .if 0
6703    cmp     r1, #0                      @ is second operand zero?
6704    beq     common_errDivideByZero
6705    .endif
6706    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6707
6708    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6709    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6710    SET_VREG(r0, r9)               @ vAA<- r0
6711    GOTO_OPCODE(ip)                     @ jump to next instruction
6712    /* 10-13 instructions */
6713
6714
6715
6716/* ------------------------------ */
6717    .balign 64
6718.L_OP_ADD_INT_LIT8: /* 0xd8 */
6719/* File: armv5te/OP_ADD_INT_LIT8.S */
6720/* File: armv5te/binopLit8.S */
6721    /*
6722     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6723     * that specifies an instruction that performs "result = r0 op r1".
6724     * This could be an ARM instruction or a function call.  (If the result
6725     * comes back in a register other than r0, you can override "result".)
6726     *
6727     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6728     * vCC (r1).  Useful for integer division and modulus.
6729     *
6730     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6731     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6732     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6733     */
6734    /* binop/lit8 vAA, vBB, #+CC */
6735    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6736    mov     r9, rINST, lsr #8           @ r9<- AA
6737    and     r2, r3, #255                @ r2<- BB
6738    GET_VREG(r0, r2)                    @ r0<- vBB
6739    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6740    .if 0
6741    @cmp     r1, #0                      @ is second operand zero?
6742    beq     common_errDivideByZero
6743    .endif
6744    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6745
6746                               @ optional op; may set condition codes
6747    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6749    SET_VREG(r0, r9)               @ vAA<- r0
6750    GOTO_OPCODE(ip)                     @ jump to next instruction
6751    /* 10-12 instructions */
6752
6753
6754
6755/* ------------------------------ */
6756    .balign 64
6757.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6758/* File: armv5te/OP_RSUB_INT_LIT8.S */
6759/* File: armv5te/binopLit8.S */
6760    /*
6761     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6762     * that specifies an instruction that performs "result = r0 op r1".
6763     * This could be an ARM instruction or a function call.  (If the result
6764     * comes back in a register other than r0, you can override "result".)
6765     *
6766     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6767     * vCC (r1).  Useful for integer division and modulus.
6768     *
6769     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6770     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6771     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6772     */
6773    /* binop/lit8 vAA, vBB, #+CC */
6774    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6775    mov     r9, rINST, lsr #8           @ r9<- AA
6776    and     r2, r3, #255                @ r2<- BB
6777    GET_VREG(r0, r2)                    @ r0<- vBB
6778    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6779    .if 0
6780    @cmp     r1, #0                      @ is second operand zero?
6781    beq     common_errDivideByZero
6782    .endif
6783    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6784
6785                               @ optional op; may set condition codes
6786    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6787    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6788    SET_VREG(r0, r9)               @ vAA<- r0
6789    GOTO_OPCODE(ip)                     @ jump to next instruction
6790    /* 10-12 instructions */
6791
6792
6793
6794/* ------------------------------ */
6795    .balign 64
6796.L_OP_MUL_INT_LIT8: /* 0xda */
6797/* File: armv5te/OP_MUL_INT_LIT8.S */
6798/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6799/* File: armv5te/binopLit8.S */
6800    /*
6801     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6802     * that specifies an instruction that performs "result = r0 op r1".
6803     * This could be an ARM instruction or a function call.  (If the result
6804     * comes back in a register other than r0, you can override "result".)
6805     *
6806     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6807     * vCC (r1).  Useful for integer division and modulus.
6808     *
6809     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6810     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6811     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6812     */
6813    /* binop/lit8 vAA, vBB, #+CC */
6814    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6815    mov     r9, rINST, lsr #8           @ r9<- AA
6816    and     r2, r3, #255                @ r2<- BB
6817    GET_VREG(r0, r2)                    @ r0<- vBB
6818    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6819    .if 0
6820    @cmp     r1, #0                      @ is second operand zero?
6821    beq     common_errDivideByZero
6822    .endif
6823    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6824
6825                               @ optional op; may set condition codes
6826    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6827    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6828    SET_VREG(r0, r9)               @ vAA<- r0
6829    GOTO_OPCODE(ip)                     @ jump to next instruction
6830    /* 10-12 instructions */
6831
6832
6833
6834/* ------------------------------ */
6835    .balign 64
6836.L_OP_DIV_INT_LIT8: /* 0xdb */
6837/* File: armv5te/OP_DIV_INT_LIT8.S */
6838/* File: armv5te/binopLit8.S */
6839    /*
6840     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6841     * that specifies an instruction that performs "result = r0 op r1".
6842     * This could be an ARM instruction or a function call.  (If the result
6843     * comes back in a register other than r0, you can override "result".)
6844     *
6845     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6846     * vCC (r1).  Useful for integer division and modulus.
6847     *
6848     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6849     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6850     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6851     */
6852    /* binop/lit8 vAA, vBB, #+CC */
6853    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6854    mov     r9, rINST, lsr #8           @ r9<- AA
6855    and     r2, r3, #255                @ r2<- BB
6856    GET_VREG(r0, r2)                    @ r0<- vBB
6857    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6858    .if 1
6859    @cmp     r1, #0                      @ is second operand zero?
6860    beq     common_errDivideByZero
6861    .endif
6862    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6863
6864                               @ optional op; may set condition codes
6865    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6867    SET_VREG(r0, r9)               @ vAA<- r0
6868    GOTO_OPCODE(ip)                     @ jump to next instruction
6869    /* 10-12 instructions */
6870
6871
6872
6873/* ------------------------------ */
6874    .balign 64
6875.L_OP_REM_INT_LIT8: /* 0xdc */
6876/* File: armv5te/OP_REM_INT_LIT8.S */
6877/* idivmod returns quotient in r0 and remainder in r1 */
6878/* File: armv5te/binopLit8.S */
6879    /*
6880     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6881     * that specifies an instruction that performs "result = r0 op r1".
6882     * This could be an ARM instruction or a function call.  (If the result
6883     * comes back in a register other than r0, you can override "result".)
6884     *
6885     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6886     * vCC (r1).  Useful for integer division and modulus.
6887     *
6888     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6889     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6890     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6891     */
6892    /* binop/lit8 vAA, vBB, #+CC */
6893    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6894    mov     r9, rINST, lsr #8           @ r9<- AA
6895    and     r2, r3, #255                @ r2<- BB
6896    GET_VREG(r0, r2)                    @ r0<- vBB
6897    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6898    .if 1
6899    @cmp     r1, #0                      @ is second operand zero?
6900    beq     common_errDivideByZero
6901    .endif
6902    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6903
6904                               @ optional op; may set condition codes
6905    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6907    SET_VREG(r1, r9)               @ vAA<- r1
6908    GOTO_OPCODE(ip)                     @ jump to next instruction
6909    /* 10-12 instructions */
6910
6911
6912
6913/* ------------------------------ */
6914    .balign 64
6915.L_OP_AND_INT_LIT8: /* 0xdd */
6916/* File: armv5te/OP_AND_INT_LIT8.S */
6917/* File: armv5te/binopLit8.S */
6918    /*
6919     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6920     * that specifies an instruction that performs "result = r0 op r1".
6921     * This could be an ARM instruction or a function call.  (If the result
6922     * comes back in a register other than r0, you can override "result".)
6923     *
6924     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6925     * vCC (r1).  Useful for integer division and modulus.
6926     *
6927     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6928     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6929     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6930     */
6931    /* binop/lit8 vAA, vBB, #+CC */
6932    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6933    mov     r9, rINST, lsr #8           @ r9<- AA
6934    and     r2, r3, #255                @ r2<- BB
6935    GET_VREG(r0, r2)                    @ r0<- vBB
6936    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6937    .if 0
6938    @cmp     r1, #0                      @ is second operand zero?
6939    beq     common_errDivideByZero
6940    .endif
6941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6942
6943                               @ optional op; may set condition codes
6944    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6946    SET_VREG(r0, r9)               @ vAA<- r0
6947    GOTO_OPCODE(ip)                     @ jump to next instruction
6948    /* 10-12 instructions */
6949
6950
6951
6952/* ------------------------------ */
6953    .balign 64
6954.L_OP_OR_INT_LIT8: /* 0xde */
6955/* File: armv5te/OP_OR_INT_LIT8.S */
6956/* File: armv5te/binopLit8.S */
6957    /*
6958     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6959     * that specifies an instruction that performs "result = r0 op r1".
6960     * This could be an ARM instruction or a function call.  (If the result
6961     * comes back in a register other than r0, you can override "result".)
6962     *
6963     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6964     * vCC (r1).  Useful for integer division and modulus.
6965     *
6966     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6967     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6968     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6969     */
6970    /* binop/lit8 vAA, vBB, #+CC */
6971    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6972    mov     r9, rINST, lsr #8           @ r9<- AA
6973    and     r2, r3, #255                @ r2<- BB
6974    GET_VREG(r0, r2)                    @ r0<- vBB
6975    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6976    .if 0
6977    @cmp     r1, #0                      @ is second operand zero?
6978    beq     common_errDivideByZero
6979    .endif
6980    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6981
6982                               @ optional op; may set condition codes
6983    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6984    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6985    SET_VREG(r0, r9)               @ vAA<- r0
6986    GOTO_OPCODE(ip)                     @ jump to next instruction
6987    /* 10-12 instructions */
6988
6989
6990
6991/* ------------------------------ */
6992    .balign 64
6993.L_OP_XOR_INT_LIT8: /* 0xdf */
6994/* File: armv5te/OP_XOR_INT_LIT8.S */
6995/* File: armv5te/binopLit8.S */
6996    /*
6997     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6998     * that specifies an instruction that performs "result = r0 op r1".
6999     * This could be an ARM instruction or a function call.  (If the result
7000     * comes back in a register other than r0, you can override "result".)
7001     *
7002     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7003     * vCC (r1).  Useful for integer division and modulus.
7004     *
7005     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7006     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7007     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7008     */
7009    /* binop/lit8 vAA, vBB, #+CC */
7010    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7011    mov     r9, rINST, lsr #8           @ r9<- AA
7012    and     r2, r3, #255                @ r2<- BB
7013    GET_VREG(r0, r2)                    @ r0<- vBB
7014    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7015    .if 0
7016    @cmp     r1, #0                      @ is second operand zero?
7017    beq     common_errDivideByZero
7018    .endif
7019    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7020
7021                               @ optional op; may set condition codes
7022    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7023    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7024    SET_VREG(r0, r9)               @ vAA<- r0
7025    GOTO_OPCODE(ip)                     @ jump to next instruction
7026    /* 10-12 instructions */
7027
7028
7029
7030/* ------------------------------ */
7031    .balign 64
7032.L_OP_SHL_INT_LIT8: /* 0xe0 */
7033/* File: armv5te/OP_SHL_INT_LIT8.S */
7034/* File: armv5te/binopLit8.S */
7035    /*
7036     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7037     * that specifies an instruction that performs "result = r0 op r1".
7038     * This could be an ARM instruction or a function call.  (If the result
7039     * comes back in a register other than r0, you can override "result".)
7040     *
7041     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7042     * vCC (r1).  Useful for integer division and modulus.
7043     *
7044     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7045     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7046     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7047     */
7048    /* binop/lit8 vAA, vBB, #+CC */
7049    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7050    mov     r9, rINST, lsr #8           @ r9<- AA
7051    and     r2, r3, #255                @ r2<- BB
7052    GET_VREG(r0, r2)                    @ r0<- vBB
7053    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7054    .if 0
7055    @cmp     r1, #0                      @ is second operand zero?
7056    beq     common_errDivideByZero
7057    .endif
7058    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7059
7060    and     r1, r1, #31                           @ optional op; may set condition codes
7061    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7063    SET_VREG(r0, r9)               @ vAA<- r0
7064    GOTO_OPCODE(ip)                     @ jump to next instruction
7065    /* 10-12 instructions */
7066
7067
7068
7069/* ------------------------------ */
7070    .balign 64
7071.L_OP_SHR_INT_LIT8: /* 0xe1 */
7072/* File: armv5te/OP_SHR_INT_LIT8.S */
7073/* File: armv5te/binopLit8.S */
7074    /*
7075     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7076     * that specifies an instruction that performs "result = r0 op r1".
7077     * This could be an ARM instruction or a function call.  (If the result
7078     * comes back in a register other than r0, you can override "result".)
7079     *
7080     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7081     * vCC (r1).  Useful for integer division and modulus.
7082     *
7083     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7084     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7085     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7086     */
7087    /* binop/lit8 vAA, vBB, #+CC */
7088    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7089    mov     r9, rINST, lsr #8           @ r9<- AA
7090    and     r2, r3, #255                @ r2<- BB
7091    GET_VREG(r0, r2)                    @ r0<- vBB
7092    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7093    .if 0
7094    @cmp     r1, #0                      @ is second operand zero?
7095    beq     common_errDivideByZero
7096    .endif
7097    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7098
7099    and     r1, r1, #31                           @ optional op; may set condition codes
7100    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7102    SET_VREG(r0, r9)               @ vAA<- r0
7103    GOTO_OPCODE(ip)                     @ jump to next instruction
7104    /* 10-12 instructions */
7105
7106
7107
7108/* ------------------------------ */
7109    .balign 64
7110.L_OP_USHR_INT_LIT8: /* 0xe2 */
7111/* File: armv5te/OP_USHR_INT_LIT8.S */
7112/* File: armv5te/binopLit8.S */
7113    /*
7114     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7115     * that specifies an instruction that performs "result = r0 op r1".
7116     * This could be an ARM instruction or a function call.  (If the result
7117     * comes back in a register other than r0, you can override "result".)
7118     *
7119     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7120     * vCC (r1).  Useful for integer division and modulus.
7121     *
7122     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7123     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7124     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7125     */
7126    /* binop/lit8 vAA, vBB, #+CC */
7127    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7128    mov     r9, rINST, lsr #8           @ r9<- AA
7129    and     r2, r3, #255                @ r2<- BB
7130    GET_VREG(r0, r2)                    @ r0<- vBB
7131    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7132    .if 0
7133    @cmp     r1, #0                      @ is second operand zero?
7134    beq     common_errDivideByZero
7135    .endif
7136    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7137
7138    and     r1, r1, #31                           @ optional op; may set condition codes
7139    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7140    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7141    SET_VREG(r0, r9)               @ vAA<- r0
7142    GOTO_OPCODE(ip)                     @ jump to next instruction
7143    /* 10-12 instructions */
7144
7145
7146
7147/* ------------------------------ */
7148    .balign 64
7149.L_OP_UNUSED_E3: /* 0xe3 */
7150/* File: armv5te/OP_UNUSED_E3.S */
7151/* File: armv5te/unused.S */
7152    bl      common_abort
7153
7154
7155
7156/* ------------------------------ */
7157    .balign 64
7158.L_OP_UNUSED_E4: /* 0xe4 */
7159/* File: armv5te/OP_UNUSED_E4.S */
7160/* File: armv5te/unused.S */
7161    bl      common_abort
7162
7163
7164
7165/* ------------------------------ */
7166    .balign 64
7167.L_OP_UNUSED_E5: /* 0xe5 */
7168/* File: armv5te/OP_UNUSED_E5.S */
7169/* File: armv5te/unused.S */
7170    bl      common_abort
7171
7172
7173
7174/* ------------------------------ */
7175    .balign 64
7176.L_OP_UNUSED_E6: /* 0xe6 */
7177/* File: armv5te/OP_UNUSED_E6.S */
7178/* File: armv5te/unused.S */
7179    bl      common_abort
7180
7181
7182
7183/* ------------------------------ */
7184    .balign 64
7185.L_OP_UNUSED_E7: /* 0xe7 */
7186/* File: armv5te/OP_UNUSED_E7.S */
7187/* File: armv5te/unused.S */
7188    bl      common_abort
7189
7190
7191
7192/* ------------------------------ */
7193    .balign 64
7194.L_OP_UNUSED_E8: /* 0xe8 */
7195/* File: armv5te/OP_UNUSED_E8.S */
7196/* File: armv5te/unused.S */
7197    bl      common_abort
7198
7199
7200
7201/* ------------------------------ */
7202    .balign 64
7203.L_OP_UNUSED_E9: /* 0xe9 */
7204/* File: armv5te/OP_UNUSED_E9.S */
7205/* File: armv5te/unused.S */
7206    bl      common_abort
7207
7208
7209
7210/* ------------------------------ */
7211    .balign 64
7212.L_OP_UNUSED_EA: /* 0xea */
7213/* File: armv5te/OP_UNUSED_EA.S */
7214/* File: armv5te/unused.S */
7215    bl      common_abort
7216
7217
7218
7219/* ------------------------------ */
7220    .balign 64
7221.L_OP_UNUSED_EB: /* 0xeb */
7222/* File: armv5te/OP_UNUSED_EB.S */
7223/* File: armv5te/unused.S */
7224    bl      common_abort
7225
7226
7227
7228/* ------------------------------ */
7229    .balign 64
7230.L_OP_BREAKPOINT: /* 0xec */
7231/* File: armv5te/OP_BREAKPOINT.S */
7232/* File: armv5te/unused.S */
7233    bl      common_abort
7234
7235
7236
7237/* ------------------------------ */
7238    .balign 64
7239.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7240/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7241    /*
7242     * Handle a throw-verification-error instruction.  This throws an
7243     * exception for an error discovered during verification.  The
7244     * exception is indicated by AA, with some detail provided by BBBB.
7245     */
7246    /* op AA, ref@BBBB */
7247    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7248    FETCH(r2, 1)                        @ r2<- BBBB
7249    EXPORT_PC()                         @ export the PC
7250    mov     r1, rINST, lsr #8           @ r1<- AA
7251    bl      dvmThrowVerificationError   @ always throws
7252    b       common_exceptionThrown      @ handle exception
7253
7254
7255/* ------------------------------ */
7256    .balign 64
7257.L_OP_EXECUTE_INLINE: /* 0xee */
7258/* File: armv5te/OP_EXECUTE_INLINE.S */
7259    /*
7260     * Execute a "native inline" instruction.
7261     *
7262     * We need to call an InlineOp4Func:
7263     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7264     *
7265     * The first four args are in r0-r3, pointer to return value storage
7266     * is on the stack.  The function's return value is a flag that tells
7267     * us if an exception was thrown.
7268     */
7269    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7270    FETCH(r10, 1)                       @ r10<- BBBB
7271    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7272    EXPORT_PC()                         @ can throw
7273    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7274    mov     r0, rINST, lsr #12          @ r0<- B
7275    str     r1, [sp]                    @ push &glue->retval
7276    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7277    add     sp, sp, #8                  @ pop stack
7278    cmp     r0, #0                      @ test boolean result of inline
7279    beq     common_exceptionThrown      @ returned false, handle exception
7280    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7281    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7282    GOTO_OPCODE(ip)                     @ jump to next instruction
7283
7284/* ------------------------------ */
7285    .balign 64
7286.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7287/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7288    /*
7289     * Execute a "native inline" instruction, using "/range" semantics.
7290     * Same idea as execute-inline, but we get the args differently.
7291     *
7292     * We need to call an InlineOp4Func:
7293     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7294     *
7295     * The first four args are in r0-r3, pointer to return value storage
7296     * is on the stack.  The function's return value is a flag that tells
7297     * us if an exception was thrown.
7298     */
7299    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7300    FETCH(r10, 1)                       @ r10<- BBBB
7301    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7302    EXPORT_PC()                         @ can throw
7303    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7304    mov     r0, rINST, lsr #8           @ r0<- AA
7305    str     r1, [sp]                    @ push &glue->retval
7306    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7307    add     sp, sp, #8                  @ pop stack
7308    cmp     r0, #0                      @ test boolean result of inline
7309    beq     common_exceptionThrown      @ returned false, handle exception
7310    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7312    GOTO_OPCODE(ip)                     @ jump to next instruction
7313
7314/* ------------------------------ */
7315    .balign 64
7316.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7317/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7318    /*
7319     * invoke-direct-empty is a no-op in a "standard" interpreter.
7320     */
7321    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7322    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7323    GOTO_OPCODE(ip)                     @ execute it
7324
7325/* ------------------------------ */
7326    .balign 64
7327.L_OP_UNUSED_F1: /* 0xf1 */
7328/* File: armv5te/OP_UNUSED_F1.S */
7329/* File: armv5te/unused.S */
7330    bl      common_abort
7331
7332
7333
7334/* ------------------------------ */
7335    .balign 64
7336.L_OP_IGET_QUICK: /* 0xf2 */
7337/* File: armv6t2/OP_IGET_QUICK.S */
7338    /* For: iget-quick, iget-object-quick */
7339    /* op vA, vB, offset@CCCC */
7340    mov     r2, rINST, lsr #12          @ r2<- B
7341    FETCH(r1, 1)                        @ r1<- field byte offset
7342    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7343    ubfx    r2, rINST, #8, #4           @ r2<- A
7344    cmp     r3, #0                      @ check object for null
7345    beq     common_errNullObject        @ object was null
7346    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7347    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7349    SET_VREG(r0, r2)                    @ fp[A]<- r0
7350    GOTO_OPCODE(ip)                     @ jump to next instruction
7351
7352
7353/* ------------------------------ */
7354    .balign 64
7355.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7356/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7357    /* iget-wide-quick vA, vB, offset@CCCC */
7358    mov     r2, rINST, lsr #12          @ r2<- B
7359    FETCH(r1, 1)                        @ r1<- field byte offset
7360    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7361    ubfx    r2, rINST, #8, #4           @ r2<- A
7362    cmp     r3, #0                      @ check object for null
7363    beq     common_errNullObject        @ object was null
7364    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7366    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7368    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7369    GOTO_OPCODE(ip)                     @ jump to next instruction
7370
7371
7372/* ------------------------------ */
7373    .balign 64
7374.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7375/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7376/* File: armv5te/OP_IGET_QUICK.S */
7377    /* For: iget-quick, iget-object-quick */
7378    /* op vA, vB, offset@CCCC */
7379    mov     r2, rINST, lsr #12          @ r2<- B
7380    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7381    FETCH(r1, 1)                        @ r1<- field byte offset
7382    cmp     r3, #0                      @ check object for null
7383    mov     r2, rINST, lsr #8           @ r2<- A(+)
7384    beq     common_errNullObject        @ object was null
7385    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7386    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7387    and     r2, r2, #15
7388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7389    SET_VREG(r0, r2)                    @ fp[A]<- r0
7390    GOTO_OPCODE(ip)                     @ jump to next instruction
7391
7392
7393
7394/* ------------------------------ */
7395    .balign 64
7396.L_OP_IPUT_QUICK: /* 0xf5 */
7397/* File: armv6t2/OP_IPUT_QUICK.S */
7398    /* For: iput-quick, iput-object-quick */
7399    /* op vA, vB, offset@CCCC */
7400    mov     r2, rINST, lsr #12          @ r2<- B
7401    FETCH(r1, 1)                        @ r1<- field byte offset
7402    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7403    ubfx    r2, rINST, #8, #4           @ r2<- A
7404    cmp     r3, #0                      @ check object for null
7405    beq     common_errNullObject        @ object was null
7406    GET_VREG(r0, r2)                    @ r0<- fp[A]
7407    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7408    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7409    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7410    GOTO_OPCODE(ip)                     @ jump to next instruction
7411
7412
7413/* ------------------------------ */
7414    .balign 64
7415.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7416/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7417    /* iput-wide-quick vA, vB, offset@CCCC */
7418    mov     r1, rINST, lsr #12          @ r1<- B
7419    ubfx    r0, rINST, #8, #4           @ r0<- A
7420    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7421    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7422    cmp     r2, #0                      @ check object for null
7423    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7424    beq     common_errNullObject        @ object was null
7425    FETCH(r3, 1)                        @ r3<- field byte offset
7426    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7427    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7429    GOTO_OPCODE(ip)                     @ jump to next instruction
7430
7431
7432/* ------------------------------ */
7433    .balign 64
7434.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7435/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7436/* File: armv5te/OP_IPUT_QUICK.S */
7437    /* For: iput-quick, iput-object-quick */
7438    /* op vA, vB, offset@CCCC */
7439    mov     r2, rINST, lsr #12          @ r2<- B
7440    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7441    FETCH(r1, 1)                        @ r1<- field byte offset
7442    cmp     r3, #0                      @ check object for null
7443    mov     r2, rINST, lsr #8           @ r2<- A(+)
7444    beq     common_errNullObject        @ object was null
7445    and     r2, r2, #15
7446    GET_VREG(r0, r2)                    @ r0<- fp[A]
7447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7448    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7449    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7450    GOTO_OPCODE(ip)                     @ jump to next instruction
7451
7452
7453
7454/* ------------------------------ */
7455    .balign 64
7456.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7457/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7458    /*
7459     * Handle an optimized virtual method call.
7460     *
7461     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7462     */
7463    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7464    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7465    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7466    FETCH(r1, 1)                        @ r1<- BBBB
7467    .if     (!0)
7468    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7469    .endif
7470    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7471    cmp     r2, #0                      @ is "this" null?
7472    beq     common_errNullObject        @ null "this", throw exception
7473    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7474    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7475    EXPORT_PC()                         @ invoke must export
7476    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7477    bl      common_invokeMethodNoRange @ continue on
7478
7479/* ------------------------------ */
7480    .balign 64
7481.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7482/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7483/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7484    /*
7485     * Handle an optimized virtual method call.
7486     *
7487     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7488     */
7489    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7490    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7491    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7492    FETCH(r1, 1)                        @ r1<- BBBB
7493    .if     (!1)
7494    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7495    .endif
7496    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7497    cmp     r2, #0                      @ is "this" null?
7498    beq     common_errNullObject        @ null "this", throw exception
7499    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7500    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7501    EXPORT_PC()                         @ invoke must export
7502    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7503    bl      common_invokeMethodRange @ continue on
7504
7505
7506/* ------------------------------ */
7507    .balign 64
7508.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7509/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7510    /*
7511     * Handle an optimized "super" method call.
7512     *
7513     * for: [opt] invoke-super-quick, invoke-super-quick/range
7514     */
7515    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7516    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7517    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7518    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7519    .if     (!0)
7520    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7521    .endif
7522    FETCH(r1, 1)                        @ r1<- BBBB
7523    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7524    EXPORT_PC()                         @ must export for invoke
7525    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7526    GET_VREG(r3, r10)                   @ r3<- "this"
7527    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7528    cmp     r3, #0                      @ null "this" ref?
7529    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7530    beq     common_errNullObject        @ "this" is null, throw exception
7531    bl      common_invokeMethodNoRange @ continue on
7532
7533
7534/* ------------------------------ */
7535    .balign 64
7536.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7537/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7538/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7539    /*
7540     * Handle an optimized "super" method call.
7541     *
7542     * for: [opt] invoke-super-quick, invoke-super-quick/range
7543     */
7544    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7545    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7546    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7547    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7548    .if     (!1)
7549    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7550    .endif
7551    FETCH(r1, 1)                        @ r1<- BBBB
7552    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7553    EXPORT_PC()                         @ must export for invoke
7554    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7555    GET_VREG(r3, r10)                   @ r3<- "this"
7556    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7557    cmp     r3, #0                      @ null "this" ref?
7558    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7559    beq     common_errNullObject        @ "this" is null, throw exception
7560    bl      common_invokeMethodRange @ continue on
7561
7562
7563
7564/* ------------------------------ */
7565    .balign 64
7566.L_OP_UNUSED_FC: /* 0xfc */
7567/* File: armv5te/OP_UNUSED_FC.S */
7568/* File: armv5te/unused.S */
7569    bl      common_abort
7570
7571
7572
7573/* ------------------------------ */
7574    .balign 64
7575.L_OP_UNUSED_FD: /* 0xfd */
7576/* File: armv5te/OP_UNUSED_FD.S */
7577/* File: armv5te/unused.S */
7578    bl      common_abort
7579
7580
7581
7582/* ------------------------------ */
7583    .balign 64
7584.L_OP_UNUSED_FE: /* 0xfe */
7585/* File: armv5te/OP_UNUSED_FE.S */
7586/* File: armv5te/unused.S */
7587    bl      common_abort
7588
7589
7590
7591/* ------------------------------ */
7592    .balign 64
7593.L_OP_UNUSED_FF: /* 0xff */
7594/* File: armv5te/OP_UNUSED_FF.S */
7595/* File: armv5te/unused.S */
7596    bl      common_abort
7597
7598
7599
7600
7601    .balign 64
7602    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7603    .global dvmAsmInstructionEnd
7604dvmAsmInstructionEnd:
7605
7606/*
7607 * ===========================================================================
7608 *  Sister implementations
7609 * ===========================================================================
7610 */
7611    .global dvmAsmSisterStart
7612    .type   dvmAsmSisterStart, %function
7613    .text
7614    .balign 4
7615dvmAsmSisterStart:
7616
7617/* continuation for OP_CONST_STRING */
7618
7619    /*
7620     * Continuation if the String has not yet been resolved.
7621     *  r1: BBBB (String ref)
7622     *  r9: target register
7623     */
7624.LOP_CONST_STRING_resolve:
7625    EXPORT_PC()
7626    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7627    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7628    bl      dvmResolveString            @ r0<- String reference
7629    cmp     r0, #0                      @ failed?
7630    beq     common_exceptionThrown      @ yup, handle the exception
7631    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7632    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7633    SET_VREG(r0, r9)                    @ vAA<- r0
7634    GOTO_OPCODE(ip)                     @ jump to next instruction
7635
7636
7637/* continuation for OP_CONST_STRING_JUMBO */
7638
7639    /*
7640     * Continuation if the String has not yet been resolved.
7641     *  r1: BBBBBBBB (String ref)
7642     *  r9: target register
7643     */
7644.LOP_CONST_STRING_JUMBO_resolve:
7645    EXPORT_PC()
7646    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7647    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7648    bl      dvmResolveString            @ r0<- String reference
7649    cmp     r0, #0                      @ failed?
7650    beq     common_exceptionThrown      @ yup, handle the exception
7651    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7652    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7653    SET_VREG(r0, r9)                    @ vAA<- r0
7654    GOTO_OPCODE(ip)                     @ jump to next instruction
7655
7656
7657/* continuation for OP_CONST_CLASS */
7658
7659    /*
7660     * Continuation if the Class has not yet been resolved.
7661     *  r1: BBBB (Class ref)
7662     *  r9: target register
7663     */
7664.LOP_CONST_CLASS_resolve:
7665    EXPORT_PC()
7666    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7667    mov     r2, #1                      @ r2<- true
7668    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7669    bl      dvmResolveClass             @ r0<- Class reference
7670    cmp     r0, #0                      @ failed?
7671    beq     common_exceptionThrown      @ yup, handle the exception
7672    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7674    SET_VREG(r0, r9)                    @ vAA<- r0
7675    GOTO_OPCODE(ip)                     @ jump to next instruction
7676
7677
7678/* continuation for OP_CHECK_CAST */
7679
7680    /*
7681     * Trivial test failed, need to perform full check.  This is common.
7682     *  r0 holds obj->clazz
7683     *  r1 holds class resolved from BBBB
7684     *  r9 holds object
7685     */
7686.LOP_CHECK_CAST_fullcheck:
7687    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7688    cmp     r0, #0                      @ failed?
7689    bne     .LOP_CHECK_CAST_okay            @ no, success
7690
7691    @ A cast has failed.  We need to throw a ClassCastException with the
7692    @ class of the object that failed to be cast.
7693    EXPORT_PC()                         @ about to throw
7694    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7695    ldr     r0, .LstrClassCastExceptionPtr
7696    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7697    bl      dvmThrowExceptionWithClassMessage
7698    b       common_exceptionThrown
7699
7700    /*
7701     * Resolution required.  This is the least-likely path.
7702     *
7703     *  r2 holds BBBB
7704     *  r9 holds object
7705     */
7706.LOP_CHECK_CAST_resolve:
7707    EXPORT_PC()                         @ resolve() could throw
7708    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7709    mov     r1, r2                      @ r1<- BBBB
7710    mov     r2, #0                      @ r2<- false
7711    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7712    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7713    cmp     r0, #0                      @ got null?
7714    beq     common_exceptionThrown      @ yes, handle exception
7715    mov     r1, r0                      @ r1<- class resolved from BBB
7716    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7717    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7718
7719.LstrClassCastExceptionPtr:
7720    .word   .LstrClassCastException
7721
7722
7723/* continuation for OP_INSTANCE_OF */
7724
7725    /*
7726     * Trivial test failed, need to perform full check.  This is common.
7727     *  r0 holds obj->clazz
7728     *  r1 holds class resolved from BBBB
7729     *  r9 holds A
7730     */
7731.LOP_INSTANCE_OF_fullcheck:
7732    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7733    @ fall through to OP_INSTANCE_OF_store
7734
7735    /*
7736     * r0 holds boolean result
7737     * r9 holds A
7738     */
7739.LOP_INSTANCE_OF_store:
7740    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7741    SET_VREG(r0, r9)                    @ vA<- r0
7742    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7743    GOTO_OPCODE(ip)                     @ jump to next instruction
7744
7745    /*
7746     * Trivial test succeeded, save and bail.
7747     *  r9 holds A
7748     */
7749.LOP_INSTANCE_OF_trivial:
7750    mov     r0, #1                      @ indicate success
7751    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7752    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7753    SET_VREG(r0, r9)                    @ vA<- r0
7754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7755    GOTO_OPCODE(ip)                     @ jump to next instruction
7756
7757    /*
7758     * Resolution required.  This is the least-likely path.
7759     *
7760     *  r3 holds BBBB
7761     *  r9 holds A
7762     */
7763.LOP_INSTANCE_OF_resolve:
7764    EXPORT_PC()                         @ resolve() could throw
7765    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7766    mov     r1, r3                      @ r1<- BBBB
7767    mov     r2, #1                      @ r2<- true
7768    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7769    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7770    cmp     r0, #0                      @ got null?
7771    beq     common_exceptionThrown      @ yes, handle exception
7772    mov     r1, r0                      @ r1<- class resolved from BBB
7773    mov     r3, rINST, lsr #12          @ r3<- B
7774    GET_VREG(r0, r3)                    @ r0<- vB (object)
7775    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7776    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7777
7778
7779/* continuation for OP_NEW_INSTANCE */
7780
7781    .balign 32                          @ minimize cache lines
7782.LOP_NEW_INSTANCE_finish: @ r0=new object
7783    mov     r3, rINST, lsr #8           @ r3<- AA
7784    cmp     r0, #0                      @ failed?
7785    beq     common_exceptionThrown      @ yes, handle the exception
7786    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7787    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7788    SET_VREG(r0, r3)                    @ vAA<- r0
7789    GOTO_OPCODE(ip)                     @ jump to next instruction
7790
7791    /*
7792     * Class initialization required.
7793     *
7794     *  r0 holds class object
7795     */
7796.LOP_NEW_INSTANCE_needinit:
7797    mov     r9, r0                      @ save r0
7798    bl      dvmInitClass                @ initialize class
7799    cmp     r0, #0                      @ check boolean result
7800    mov     r0, r9                      @ restore r0
7801    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7802    b       common_exceptionThrown      @ failed, deal with init exception
7803
7804    /*
7805     * Resolution required.  This is the least-likely path.
7806     *
7807     *  r1 holds BBBB
7808     */
7809.LOP_NEW_INSTANCE_resolve:
7810    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7811    mov     r2, #0                      @ r2<- false
7812    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7813    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7814    cmp     r0, #0                      @ got null?
7815    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7816    b       common_exceptionThrown      @ yes, handle exception
7817
7818.LstrInstantiationErrorPtr:
7819    .word   .LstrInstantiationError
7820
7821
7822/* continuation for OP_NEW_ARRAY */
7823
7824
7825    /*
7826     * Resolve class.  (This is an uncommon case.)
7827     *
7828     *  r1 holds array length
7829     *  r2 holds class ref CCCC
7830     */
7831.LOP_NEW_ARRAY_resolve:
7832    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7833    mov     r9, r1                      @ r9<- length (save)
7834    mov     r1, r2                      @ r1<- CCCC
7835    mov     r2, #0                      @ r2<- false
7836    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7837    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7838    cmp     r0, #0                      @ got null?
7839    mov     r1, r9                      @ r1<- length (restore)
7840    beq     common_exceptionThrown      @ yes, handle exception
7841    @ fall through to OP_NEW_ARRAY_finish
7842
7843    /*
7844     * Finish allocation.
7845     *
7846     *  r0 holds class
7847     *  r1 holds array length
7848     */
7849.LOP_NEW_ARRAY_finish:
7850    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7851    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7852    cmp     r0, #0                      @ failed?
7853    mov     r2, rINST, lsr #8           @ r2<- A+
7854    beq     common_exceptionThrown      @ yes, handle the exception
7855    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7856    and     r2, r2, #15                 @ r2<- A
7857    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7858    SET_VREG(r0, r2)                    @ vA<- r0
7859    GOTO_OPCODE(ip)                     @ jump to next instruction
7860
7861
7862/* continuation for OP_FILLED_NEW_ARRAY */
7863
7864    /*
7865     * On entry:
7866     *  r0 holds array class
7867     *  r10 holds AA or BA
7868     */
7869.LOP_FILLED_NEW_ARRAY_continue:
7870    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7871    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7872    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7873    .if     0
7874    mov     r1, r10                     @ r1<- AA (length)
7875    .else
7876    mov     r1, r10, lsr #4             @ r1<- B (length)
7877    .endif
7878    cmp     r3, #'I'                    @ array of ints?
7879    cmpne   r3, #'L'                    @ array of objects?
7880    cmpne   r3, #'['                    @ array of arrays?
7881    mov     r9, r1                      @ save length in r9
7882    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7883    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7884    cmp     r0, #0                      @ null return?
7885    beq     common_exceptionThrown      @ alloc failed, handle exception
7886
7887    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7888    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7889    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7890    subs    r9, r9, #1                  @ length--, check for neg
7891    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7892    bmi     2f                          @ was zero, bail
7893
7894    @ copy values from registers into the array
7895    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7896    .if     0
7897    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
78981:  ldr     r3, [r2], #4                @ r3<- *r2++
7899    subs    r9, r9, #1                  @ count--
7900    str     r3, [r0], #4                @ *contents++ = vX
7901    bpl     1b
7902    @ continue at 2
7903    .else
7904    cmp     r9, #4                      @ length was initially 5?
7905    and     r2, r10, #15                @ r2<- A
7906    bne     1f                          @ <= 4 args, branch
7907    GET_VREG(r3, r2)                    @ r3<- vA
7908    sub     r9, r9, #1                  @ count--
7909    str     r3, [r0, #16]               @ contents[4] = vA
79101:  and     r2, r1, #15                 @ r2<- F/E/D/C
7911    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7912    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7913    subs    r9, r9, #1                  @ count--
7914    str     r3, [r0], #4                @ *contents++ = vX
7915    bpl     1b
7916    @ continue at 2
7917    .endif
7918
79192:
7920    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7921    GOTO_OPCODE(ip)                     @ execute it
7922
7923    /*
7924     * Throw an exception indicating that we have not implemented this
7925     * mode of filled-new-array.
7926     */
7927.LOP_FILLED_NEW_ARRAY_notimpl:
7928    ldr     r0, .L_strInternalError
7929    ldr     r1, .L_strFilledNewArrayNotImpl
7930    bl      dvmThrowException
7931    b       common_exceptionThrown
7932
7933    .if     (!0)                 @ define in one or the other, not both
7934.L_strFilledNewArrayNotImpl:
7935    .word   .LstrFilledNewArrayNotImpl
7936.L_strInternalError:
7937    .word   .LstrInternalError
7938    .endif
7939
7940
7941/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7942
7943    /*
7944     * On entry:
7945     *  r0 holds array class
7946     *  r10 holds AA or BA
7947     */
7948.LOP_FILLED_NEW_ARRAY_RANGE_continue:
7949    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7950    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7951    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7952    .if     1
7953    mov     r1, r10                     @ r1<- AA (length)
7954    .else
7955    mov     r1, r10, lsr #4             @ r1<- B (length)
7956    .endif
7957    cmp     r3, #'I'                    @ array of ints?
7958    cmpne   r3, #'L'                    @ array of objects?
7959    cmpne   r3, #'['                    @ array of arrays?
7960    mov     r9, r1                      @ save length in r9
7961    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7962    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7963    cmp     r0, #0                      @ null return?
7964    beq     common_exceptionThrown      @ alloc failed, handle exception
7965
7966    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7967    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7968    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7969    subs    r9, r9, #1                  @ length--, check for neg
7970    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7971    bmi     2f                          @ was zero, bail
7972
7973    @ copy values from registers into the array
7974    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7975    .if     1
7976    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79771:  ldr     r3, [r2], #4                @ r3<- *r2++
7978    subs    r9, r9, #1                  @ count--
7979    str     r3, [r0], #4                @ *contents++ = vX
7980    bpl     1b
7981    @ continue at 2
7982    .else
7983    cmp     r9, #4                      @ length was initially 5?
7984    and     r2, r10, #15                @ r2<- A
7985    bne     1f                          @ <= 4 args, branch
7986    GET_VREG(r3, r2)                    @ r3<- vA
7987    sub     r9, r9, #1                  @ count--
7988    str     r3, [r0, #16]               @ contents[4] = vA
79891:  and     r2, r1, #15                 @ r2<- F/E/D/C
7990    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7991    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7992    subs    r9, r9, #1                  @ count--
7993    str     r3, [r0], #4                @ *contents++ = vX
7994    bpl     1b
7995    @ continue at 2
7996    .endif
7997
79982:
7999    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8000    GOTO_OPCODE(ip)                     @ execute it
8001
8002    /*
8003     * Throw an exception indicating that we have not implemented this
8004     * mode of filled-new-array.
8005     */
8006.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8007    ldr     r0, .L_strInternalError
8008    ldr     r1, .L_strFilledNewArrayNotImpl
8009    bl      dvmThrowException
8010    b       common_exceptionThrown
8011
8012    .if     (!1)                 @ define in one or the other, not both
8013.L_strFilledNewArrayNotImpl:
8014    .word   .LstrFilledNewArrayNotImpl
8015.L_strInternalError:
8016    .word   .LstrInternalError
8017    .endif
8018
8019
8020/* continuation for OP_CMPL_FLOAT */
8021.LOP_CMPL_FLOAT_finish:
8022    SET_VREG(r0, r9)                    @ vAA<- r0
8023    GOTO_OPCODE(ip)                     @ jump to next instruction
8024
8025
8026/* continuation for OP_CMPG_FLOAT */
8027.LOP_CMPG_FLOAT_finish:
8028    SET_VREG(r0, r9)                    @ vAA<- r0
8029    GOTO_OPCODE(ip)                     @ jump to next instruction
8030
8031
8032/* continuation for OP_CMPL_DOUBLE */
8033.LOP_CMPL_DOUBLE_finish:
8034    SET_VREG(r0, r9)                    @ vAA<- r0
8035    GOTO_OPCODE(ip)                     @ jump to next instruction
8036
8037
8038/* continuation for OP_CMPG_DOUBLE */
8039.LOP_CMPG_DOUBLE_finish:
8040    SET_VREG(r0, r9)                    @ vAA<- r0
8041    GOTO_OPCODE(ip)                     @ jump to next instruction
8042
8043
8044/* continuation for OP_CMP_LONG */
8045
8046.LOP_CMP_LONG_less:
8047    mvn     r1, #0                      @ r1<- -1
8048    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8049    @ instead, we just replicate the tail end.
8050    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8051    SET_VREG(r1, r9)                    @ vAA<- r1
8052    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8053    GOTO_OPCODE(ip)                     @ jump to next instruction
8054
8055.LOP_CMP_LONG_greater:
8056    mov     r1, #1                      @ r1<- 1
8057    @ fall through to _finish
8058
8059.LOP_CMP_LONG_finish:
8060    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8061    SET_VREG(r1, r9)                    @ vAA<- r1
8062    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8063    GOTO_OPCODE(ip)                     @ jump to next instruction
8064
8065
8066/* continuation for OP_AGET_WIDE */
8067
8068.LOP_AGET_WIDE_finish:
8069    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8070    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8071    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8072    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8073    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8074    GOTO_OPCODE(ip)                     @ jump to next instruction
8075
8076
8077/* continuation for OP_APUT_WIDE */
8078
8079.LOP_APUT_WIDE_finish:
8080    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8081    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8082    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8083    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8084    GOTO_OPCODE(ip)                     @ jump to next instruction
8085
8086
8087/* continuation for OP_APUT_OBJECT */
8088    /*
8089     * On entry:
8090     *  r1 = vBB (arrayObj)
8091     *  r9 = vAA (obj)
8092     *  r10 = offset into array (vBB + vCC * width)
8093     */
8094.LOP_APUT_OBJECT_finish:
8095    cmp     r9, #0                      @ storing null reference?
8096    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8097    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8098    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8099    bl      dvmCanPutArrayElement       @ test object type vs. array type
8100    cmp     r0, #0                      @ okay?
8101    beq     common_errArrayStore        @ no
8102.LOP_APUT_OBJECT_skip_check:
8103    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8105    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8106    GOTO_OPCODE(ip)                     @ jump to next instruction
8107
8108
8109/* continuation for OP_IGET */
8110
8111    /*
8112     * Currently:
8113     *  r0 holds resolved field
8114     *  r9 holds object
8115     */
8116.LOP_IGET_finish:
8117    @bl      common_squeak0
8118    cmp     r9, #0                      @ check object for null
8119    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8120    beq     common_errNullObject        @ object was null
8121    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8122    ubfx    r2, rINST, #8, #4           @ r2<- A
8123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8124    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8125    SET_VREG(r0, r2)                    @ fp[A]<- r0
8126    GOTO_OPCODE(ip)                     @ jump to next instruction
8127
8128
8129/* continuation for OP_IGET_WIDE */
8130
8131    /*
8132     * Currently:
8133     *  r0 holds resolved field
8134     *  r9 holds object
8135     */
8136.LOP_IGET_WIDE_finish:
8137    cmp     r9, #0                      @ check object for null
8138    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8139    beq     common_errNullObject        @ object was null
8140    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8141    ubfx    r2, rINST, #8, #4           @ r2<- A
8142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8143    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8145    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8146    GOTO_OPCODE(ip)                     @ jump to next instruction
8147
8148
8149/* continuation for OP_IGET_OBJECT */
8150
8151    /*
8152     * Currently:
8153     *  r0 holds resolved field
8154     *  r9 holds object
8155     */
8156.LOP_IGET_OBJECT_finish:
8157    @bl      common_squeak0
8158    cmp     r9, #0                      @ check object for null
8159    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8160    beq     common_errNullObject        @ object was null
8161    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8162    mov     r2, rINST, lsr #8           @ r2<- A+
8163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8164    and     r2, r2, #15                 @ r2<- A
8165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8166    SET_VREG(r0, r2)                    @ fp[A]<- r0
8167    GOTO_OPCODE(ip)                     @ jump to next instruction
8168
8169
8170/* continuation for OP_IGET_BOOLEAN */
8171
8172    /*
8173     * Currently:
8174     *  r0 holds resolved field
8175     *  r9 holds object
8176     */
8177.LOP_IGET_BOOLEAN_finish:
8178    @bl      common_squeak1
8179    cmp     r9, #0                      @ check object for null
8180    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8181    beq     common_errNullObject        @ object was null
8182    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8183    mov     r2, rINST, lsr #8           @ r2<- A+
8184    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8185    and     r2, r2, #15                 @ r2<- A
8186    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8187    SET_VREG(r0, r2)                    @ fp[A]<- r0
8188    GOTO_OPCODE(ip)                     @ jump to next instruction
8189
8190
8191/* continuation for OP_IGET_BYTE */
8192
8193    /*
8194     * Currently:
8195     *  r0 holds resolved field
8196     *  r9 holds object
8197     */
8198.LOP_IGET_BYTE_finish:
8199    @bl      common_squeak2
8200    cmp     r9, #0                      @ check object for null
8201    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8202    beq     common_errNullObject        @ object was null
8203    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8204    mov     r2, rINST, lsr #8           @ r2<- A+
8205    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8206    and     r2, r2, #15                 @ r2<- A
8207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8208    SET_VREG(r0, r2)                    @ fp[A]<- r0
8209    GOTO_OPCODE(ip)                     @ jump to next instruction
8210
8211
8212/* continuation for OP_IGET_CHAR */
8213
8214    /*
8215     * Currently:
8216     *  r0 holds resolved field
8217     *  r9 holds object
8218     */
8219.LOP_IGET_CHAR_finish:
8220    @bl      common_squeak3
8221    cmp     r9, #0                      @ check object for null
8222    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8223    beq     common_errNullObject        @ object was null
8224    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8225    mov     r2, rINST, lsr #8           @ r2<- A+
8226    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8227    and     r2, r2, #15                 @ r2<- A
8228    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8229    SET_VREG(r0, r2)                    @ fp[A]<- r0
8230    GOTO_OPCODE(ip)                     @ jump to next instruction
8231
8232
8233/* continuation for OP_IGET_SHORT */
8234
8235    /*
8236     * Currently:
8237     *  r0 holds resolved field
8238     *  r9 holds object
8239     */
8240.LOP_IGET_SHORT_finish:
8241    @bl      common_squeak4
8242    cmp     r9, #0                      @ check object for null
8243    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8244    beq     common_errNullObject        @ object was null
8245    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8246    mov     r2, rINST, lsr #8           @ r2<- A+
8247    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8248    and     r2, r2, #15                 @ r2<- A
8249    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8250    SET_VREG(r0, r2)                    @ fp[A]<- r0
8251    GOTO_OPCODE(ip)                     @ jump to next instruction
8252
8253
8254/* continuation for OP_IPUT */
8255
8256    /*
8257     * Currently:
8258     *  r0 holds resolved field
8259     *  r9 holds object
8260     */
8261.LOP_IPUT_finish:
8262    @bl      common_squeak0
8263    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8264    ubfx    r1, rINST, #8, #4           @ r1<- A
8265    cmp     r9, #0                      @ check object for null
8266    GET_VREG(r0, r1)                    @ r0<- fp[A]
8267    beq     common_errNullObject        @ object was null
8268    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8270    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8271    GOTO_OPCODE(ip)                     @ jump to next instruction
8272
8273
8274/* continuation for OP_IPUT_WIDE */
8275
8276    /*
8277     * Currently:
8278     *  r0 holds resolved field
8279     *  r9 holds object
8280     */
8281.LOP_IPUT_WIDE_finish:
8282    ubfx    r2, rINST, #8, #4           @ r2<- A
8283    cmp     r9, #0                      @ check object for null
8284    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8285    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8286    beq     common_errNullObject        @ object was null
8287    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8288    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8289    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8290    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8291    GOTO_OPCODE(ip)                     @ jump to next instruction
8292
8293
8294/* continuation for OP_IPUT_OBJECT */
8295
8296    /*
8297     * Currently:
8298     *  r0 holds resolved field
8299     *  r9 holds object
8300     */
8301.LOP_IPUT_OBJECT_finish:
8302    @bl      common_squeak0
8303    mov     r1, rINST, lsr #8           @ r1<- A+
8304    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8305    and     r1, r1, #15                 @ r1<- A
8306    cmp     r9, #0                      @ check object for null
8307    GET_VREG(r0, r1)                    @ r0<- fp[A]
8308    beq     common_errNullObject        @ object was null
8309    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8310    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8311    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8312    GOTO_OPCODE(ip)                     @ jump to next instruction
8313
8314
8315/* continuation for OP_IPUT_BOOLEAN */
8316
8317    /*
8318     * Currently:
8319     *  r0 holds resolved field
8320     *  r9 holds object
8321     */
8322.LOP_IPUT_BOOLEAN_finish:
8323    @bl      common_squeak1
8324    mov     r1, rINST, lsr #8           @ r1<- A+
8325    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8326    and     r1, r1, #15                 @ r1<- A
8327    cmp     r9, #0                      @ check object for null
8328    GET_VREG(r0, r1)                    @ r0<- fp[A]
8329    beq     common_errNullObject        @ object was null
8330    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8331    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8332    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8333    GOTO_OPCODE(ip)                     @ jump to next instruction
8334
8335
8336/* continuation for OP_IPUT_BYTE */
8337
8338    /*
8339     * Currently:
8340     *  r0 holds resolved field
8341     *  r9 holds object
8342     */
8343.LOP_IPUT_BYTE_finish:
8344    @bl      common_squeak2
8345    mov     r1, rINST, lsr #8           @ r1<- A+
8346    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8347    and     r1, r1, #15                 @ r1<- A
8348    cmp     r9, #0                      @ check object for null
8349    GET_VREG(r0, r1)                    @ r0<- fp[A]
8350    beq     common_errNullObject        @ object was null
8351    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8353    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8354    GOTO_OPCODE(ip)                     @ jump to next instruction
8355
8356
8357/* continuation for OP_IPUT_CHAR */
8358
8359    /*
8360     * Currently:
8361     *  r0 holds resolved field
8362     *  r9 holds object
8363     */
8364.LOP_IPUT_CHAR_finish:
8365    @bl      common_squeak3
8366    mov     r1, rINST, lsr #8           @ r1<- A+
8367    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8368    and     r1, r1, #15                 @ r1<- A
8369    cmp     r9, #0                      @ check object for null
8370    GET_VREG(r0, r1)                    @ r0<- fp[A]
8371    beq     common_errNullObject        @ object was null
8372    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8373    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8374    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8375    GOTO_OPCODE(ip)                     @ jump to next instruction
8376
8377
8378/* continuation for OP_IPUT_SHORT */
8379
8380    /*
8381     * Currently:
8382     *  r0 holds resolved field
8383     *  r9 holds object
8384     */
8385.LOP_IPUT_SHORT_finish:
8386    @bl      common_squeak4
8387    mov     r1, rINST, lsr #8           @ r1<- A+
8388    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8389    and     r1, r1, #15                 @ r1<- A
8390    cmp     r9, #0                      @ check object for null
8391    GET_VREG(r0, r1)                    @ r0<- fp[A]
8392    beq     common_errNullObject        @ object was null
8393    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8394    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8395    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8396    GOTO_OPCODE(ip)                     @ jump to next instruction
8397
8398
8399/* continuation for OP_SGET */
8400
8401    /*
8402     * Continuation if the field has not yet been resolved.
8403     *  r1: BBBB field ref
8404     */
8405.LOP_SGET_resolve:
8406    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8407    EXPORT_PC()                         @ resolve() could throw, so export now
8408    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8409    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8410    cmp     r0, #0                      @ success?
8411    bne     .LOP_SGET_finish          @ yes, finish
8412    b       common_exceptionThrown      @ no, handle exception
8413
8414
8415/* continuation for OP_SGET_WIDE */
8416
8417    /*
8418     * Continuation if the field has not yet been resolved.
8419     *  r1: BBBB field ref
8420     */
8421.LOP_SGET_WIDE_resolve:
8422    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8423    EXPORT_PC()                         @ resolve() could throw, so export now
8424    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8425    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8426    cmp     r0, #0                      @ success?
8427    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8428    b       common_exceptionThrown      @ no, handle exception
8429
8430
8431/* continuation for OP_SGET_OBJECT */
8432
8433    /*
8434     * Continuation if the field has not yet been resolved.
8435     *  r1: BBBB field ref
8436     */
8437.LOP_SGET_OBJECT_resolve:
8438    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8439    EXPORT_PC()                         @ resolve() could throw, so export now
8440    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8441    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8442    cmp     r0, #0                      @ success?
8443    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8444    b       common_exceptionThrown      @ no, handle exception
8445
8446
8447/* continuation for OP_SGET_BOOLEAN */
8448
8449    /*
8450     * Continuation if the field has not yet been resolved.
8451     *  r1: BBBB field ref
8452     */
8453.LOP_SGET_BOOLEAN_resolve:
8454    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8455    EXPORT_PC()                         @ resolve() could throw, so export now
8456    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8457    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8458    cmp     r0, #0                      @ success?
8459    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8460    b       common_exceptionThrown      @ no, handle exception
8461
8462
8463/* continuation for OP_SGET_BYTE */
8464
8465    /*
8466     * Continuation if the field has not yet been resolved.
8467     *  r1: BBBB field ref
8468     */
8469.LOP_SGET_BYTE_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_BYTE_finish          @ yes, finish
8476    b       common_exceptionThrown      @ no, handle exception
8477
8478
8479/* continuation for OP_SGET_CHAR */
8480
8481    /*
8482     * Continuation if the field has not yet been resolved.
8483     *  r1: BBBB field ref
8484     */
8485.LOP_SGET_CHAR_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_CHAR_finish          @ yes, finish
8492    b       common_exceptionThrown      @ no, handle exception
8493
8494
8495/* continuation for OP_SGET_SHORT */
8496
8497    /*
8498     * Continuation if the field has not yet been resolved.
8499     *  r1: BBBB field ref
8500     */
8501.LOP_SGET_SHORT_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_SHORT_finish          @ yes, finish
8508    b       common_exceptionThrown      @ no, handle exception
8509
8510
8511/* continuation for OP_SPUT */
8512
8513    /*
8514     * Continuation if the field has not yet been resolved.
8515     *  r1: BBBB field ref
8516     */
8517.LOP_SPUT_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_SPUT_finish          @ yes, finish
8524    b       common_exceptionThrown      @ no, handle exception
8525
8526
8527/* continuation for OP_SPUT_WIDE */
8528
8529    /*
8530     * Continuation if the field has not yet been resolved.
8531     *  r1: BBBB field ref
8532     *  r9: &fp[AA]
8533     */
8534.LOP_SPUT_WIDE_resolve:
8535    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8536    EXPORT_PC()                         @ resolve() could throw, so export now
8537    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8538    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8539    cmp     r0, #0                      @ success?
8540    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8541    b       common_exceptionThrown      @ no, handle exception
8542
8543
8544/* continuation for OP_SPUT_OBJECT */
8545
8546    /*
8547     * Continuation if the field has not yet been resolved.
8548     *  r1: BBBB field ref
8549     */
8550.LOP_SPUT_OBJECT_resolve:
8551    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8552    EXPORT_PC()                         @ resolve() could throw, so export now
8553    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8554    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8555    cmp     r0, #0                      @ success?
8556    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8557    b       common_exceptionThrown      @ no, handle exception
8558
8559
8560/* continuation for OP_SPUT_BOOLEAN */
8561
8562    /*
8563     * Continuation if the field has not yet been resolved.
8564     *  r1: BBBB field ref
8565     */
8566.LOP_SPUT_BOOLEAN_resolve:
8567    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8568    EXPORT_PC()                         @ resolve() could throw, so export now
8569    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8570    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8571    cmp     r0, #0                      @ success?
8572    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8573    b       common_exceptionThrown      @ no, handle exception
8574
8575
8576/* continuation for OP_SPUT_BYTE */
8577
8578    /*
8579     * Continuation if the field has not yet been resolved.
8580     *  r1: BBBB field ref
8581     */
8582.LOP_SPUT_BYTE_resolve:
8583    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8584    EXPORT_PC()                         @ resolve() could throw, so export now
8585    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8586    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8587    cmp     r0, #0                      @ success?
8588    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8589    b       common_exceptionThrown      @ no, handle exception
8590
8591
8592/* continuation for OP_SPUT_CHAR */
8593
8594    /*
8595     * Continuation if the field has not yet been resolved.
8596     *  r1: BBBB field ref
8597     */
8598.LOP_SPUT_CHAR_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_CHAR_finish          @ yes, finish
8605    b       common_exceptionThrown      @ no, handle exception
8606
8607
8608/* continuation for OP_SPUT_SHORT */
8609
8610    /*
8611     * Continuation if the field has not yet been resolved.
8612     *  r1: BBBB field ref
8613     */
8614.LOP_SPUT_SHORT_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_SHORT_finish          @ yes, finish
8621    b       common_exceptionThrown      @ no, handle exception
8622
8623
8624/* continuation for OP_INVOKE_VIRTUAL */
8625
8626    /*
8627     * At this point:
8628     *  r0 = resolved base method
8629     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8630     */
8631.LOP_INVOKE_VIRTUAL_continue:
8632    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8633    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8634    cmp     r1, #0                      @ is "this" null?
8635    beq     common_errNullObject        @ null "this", throw exception
8636    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8637    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8638    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8639    bl      common_invokeMethodNoRange @ continue on
8640
8641
8642/* continuation for OP_INVOKE_SUPER */
8643
8644    /*
8645     * At this point:
8646     *  r0 = resolved base method
8647     *  r9 = method->clazz
8648     */
8649.LOP_INVOKE_SUPER_continue:
8650    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8651    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8652    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8653    EXPORT_PC()                         @ must export for invoke
8654    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8655    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8656    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8657    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8658    bl      common_invokeMethodNoRange @ continue on
8659
8660.LOP_INVOKE_SUPER_resolve:
8661    mov     r0, r9                      @ r0<- method->clazz
8662    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8663    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8664    cmp     r0, #0                      @ got null?
8665    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8666    b       common_exceptionThrown      @ yes, handle exception
8667
8668    /*
8669     * Throw a NoSuchMethodError with the method name as the message.
8670     *  r0 = resolved base method
8671     */
8672.LOP_INVOKE_SUPER_nsm:
8673    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8674    b       common_errNoSuchMethod
8675
8676
8677/* continuation for OP_INVOKE_DIRECT */
8678
8679    /*
8680     * On entry:
8681     *  r1 = reference (BBBB or CCCC)
8682     *  r10 = "this" register
8683     */
8684.LOP_INVOKE_DIRECT_resolve:
8685    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8686    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8687    mov     r2, #METHOD_DIRECT          @ resolver method type
8688    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8689    cmp     r0, #0                      @ got null?
8690    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8691    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8692    b       common_exceptionThrown      @ yes, handle exception
8693
8694
8695/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8696
8697    /*
8698     * At this point:
8699     *  r0 = resolved base method
8700     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8701     */
8702.LOP_INVOKE_VIRTUAL_RANGE_continue:
8703    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8704    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8705    cmp     r1, #0                      @ is "this" null?
8706    beq     common_errNullObject        @ null "this", throw exception
8707    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8708    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8709    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8710    bl      common_invokeMethodRange @ continue on
8711
8712
8713/* continuation for OP_INVOKE_SUPER_RANGE */
8714
8715    /*
8716     * At this point:
8717     *  r0 = resolved base method
8718     *  r9 = method->clazz
8719     */
8720.LOP_INVOKE_SUPER_RANGE_continue:
8721    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8722    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8723    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8724    EXPORT_PC()                         @ must export for invoke
8725    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8726    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8727    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8728    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8729    bl      common_invokeMethodRange @ continue on
8730
8731.LOP_INVOKE_SUPER_RANGE_resolve:
8732    mov     r0, r9                      @ r0<- method->clazz
8733    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8734    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8735    cmp     r0, #0                      @ got null?
8736    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8737    b       common_exceptionThrown      @ yes, handle exception
8738
8739    /*
8740     * Throw a NoSuchMethodError with the method name as the message.
8741     *  r0 = resolved base method
8742     */
8743.LOP_INVOKE_SUPER_RANGE_nsm:
8744    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8745    b       common_errNoSuchMethod
8746
8747
8748/* continuation for OP_INVOKE_DIRECT_RANGE */
8749
8750    /*
8751     * On entry:
8752     *  r1 = reference (BBBB or CCCC)
8753     *  r10 = "this" register
8754     */
8755.LOP_INVOKE_DIRECT_RANGE_resolve:
8756    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8757    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8758    mov     r2, #METHOD_DIRECT          @ resolver method type
8759    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8760    cmp     r0, #0                      @ got null?
8761    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8762    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8763    b       common_exceptionThrown      @ yes, handle exception
8764
8765
8766/* continuation for OP_FLOAT_TO_LONG */
8767/*
8768 * Convert the float in r0 to a long in r0/r1.
8769 *
8770 * We have to clip values to long min/max per the specification.  The
8771 * expected common case is a "reasonable" value that converts directly
8772 * to modest integer.  The EABI convert function isn't doing this for us.
8773 */
8774f2l_doconv:
8775    stmfd   sp!, {r4, lr}
8776    mov     r1, #0x5f000000             @ (float)maxlong
8777    mov     r4, r0
8778    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8779    cmp     r0, #0                      @ nonzero == yes
8780    mvnne   r0, #0                      @ return maxlong (7fffffff)
8781    mvnne   r1, #0x80000000
8782    ldmnefd sp!, {r4, pc}
8783
8784    mov     r0, r4                      @ recover arg
8785    mov     r1, #0xdf000000             @ (float)minlong
8786    bl      __aeabi_fcmple              @ is arg <= minlong?
8787    cmp     r0, #0                      @ nonzero == yes
8788    movne   r0, #0                      @ return minlong (80000000)
8789    movne   r1, #0x80000000
8790    ldmnefd sp!, {r4, pc}
8791
8792    mov     r0, r4                      @ recover arg
8793    mov     r1, r4
8794    bl      __aeabi_fcmpeq              @ is arg == self?
8795    cmp     r0, #0                      @ zero == no
8796    moveq   r1, #0                      @ return zero for NaN
8797    ldmeqfd sp!, {r4, pc}
8798
8799    mov     r0, r4                      @ recover arg
8800    bl      __aeabi_f2lz                @ convert float to long
8801    ldmfd   sp!, {r4, pc}
8802
8803
8804/* continuation for OP_DOUBLE_TO_LONG */
8805/*
8806 * Convert the double in r0/r1 to a long in r0/r1.
8807 *
8808 * We have to clip values to long min/max per the specification.  The
8809 * expected common case is a "reasonable" value that converts directly
8810 * to modest integer.  The EABI convert function isn't doing this for us.
8811 */
8812d2l_doconv:
8813    stmfd   sp!, {r4, r5, lr}           @ save regs
8814    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8815    add     r3, #0x00e00000             @  0x43e00000
8816    mov     r2, #0                      @ maxlong, as a double (low word)
8817    sub     sp, sp, #4                  @ align for EABI
8818    mov     r4, r0                      @ save a copy of r0
8819    mov     r5, r1                      @  and r1
8820    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8821    cmp     r0, #0                      @ nonzero == yes
8822    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8823    mvnne   r1, #0x80000000
8824    bne     1f
8825
8826    mov     r0, r4                      @ recover arg
8827    mov     r1, r5
8828    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8829    add     r3, #0x00e00000             @  0xc3e00000
8830    mov     r2, #0                      @ minlong, as a double (low word)
8831    bl      __aeabi_dcmple              @ is arg <= minlong?
8832    cmp     r0, #0                      @ nonzero == yes
8833    movne   r0, #0                      @ return minlong (8000000000000000)
8834    movne   r1, #0x80000000
8835    bne     1f
8836
8837    mov     r0, r4                      @ recover arg
8838    mov     r1, r5
8839    mov     r2, r4                      @ compare against self
8840    mov     r3, r5
8841    bl      __aeabi_dcmpeq              @ is arg == self?
8842    cmp     r0, #0                      @ zero == no
8843    moveq   r1, #0                      @ return zero for NaN
8844    beq     1f
8845
8846    mov     r0, r4                      @ recover arg
8847    mov     r1, r5
8848    bl      __aeabi_d2lz                @ convert double to long
8849
88501:
8851    add     sp, sp, #4
8852    ldmfd   sp!, {r4, r5, pc}
8853
8854
8855/* continuation for OP_MUL_LONG */
8856
8857.LOP_MUL_LONG_finish:
8858    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8859    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8860    GOTO_OPCODE(ip)                     @ jump to next instruction
8861
8862
8863/* continuation for OP_SHL_LONG */
8864
8865.LOP_SHL_LONG_finish:
8866    mov     r0, r0, asl r2              @  r0<- r0 << r2
8867    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8868    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8869    GOTO_OPCODE(ip)                     @ jump to next instruction
8870
8871
8872/* continuation for OP_SHR_LONG */
8873
8874.LOP_SHR_LONG_finish:
8875    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8876    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8877    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8878    GOTO_OPCODE(ip)                     @ jump to next instruction
8879
8880
8881/* continuation for OP_USHR_LONG */
8882
8883.LOP_USHR_LONG_finish:
8884    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8885    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8886    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8887    GOTO_OPCODE(ip)                     @ jump to next instruction
8888
8889
8890/* continuation for OP_SHL_LONG_2ADDR */
8891
8892.LOP_SHL_LONG_2ADDR_finish:
8893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8894    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8895    GOTO_OPCODE(ip)                     @ jump to next instruction
8896
8897
8898/* continuation for OP_SHR_LONG_2ADDR */
8899
8900.LOP_SHR_LONG_2ADDR_finish:
8901    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8902    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8903    GOTO_OPCODE(ip)                     @ jump to next instruction
8904
8905
8906/* continuation for OP_USHR_LONG_2ADDR */
8907
8908.LOP_USHR_LONG_2ADDR_finish:
8909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8910    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8911    GOTO_OPCODE(ip)                     @ jump to next instruction
8912
8913
8914/* continuation for OP_EXECUTE_INLINE */
8915
8916    /*
8917     * Extract args, call function.
8918     *  r0 = #of args (0-4)
8919     *  r10 = call index
8920     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8921     *
8922     * Other ideas:
8923     * - Use a jump table from the main piece to jump directly into the
8924     *   AND/LDR pairs.  Costs a data load, saves a branch.
8925     * - Have five separate pieces that do the loading, so we can work the
8926     *   interleave a little better.  Increases code size.
8927     */
8928.LOP_EXECUTE_INLINE_continue:
8929    rsb     r0, r0, #4                  @ r0<- 4-r0
8930    FETCH(r9, 2)                        @ r9<- FEDC
8931    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8932    bl      common_abort                @ (skipped due to ARM prefetch)
89334:  and     ip, r9, #0xf000             @ isolate F
8934    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89353:  and     ip, r9, #0x0f00             @ isolate E
8936    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89372:  and     ip, r9, #0x00f0             @ isolate D
8938    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
89391:  and     ip, r9, #0x000f             @ isolate C
8940    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
89410:
8942    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8943    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8944    @ (not reached)
8945
8946.LOP_EXECUTE_INLINE_table:
8947    .word   gDvmInlineOpsTable
8948
8949
8950/* continuation for OP_EXECUTE_INLINE_RANGE */
8951
8952    /*
8953     * Extract args, call function.
8954     *  r0 = #of args (0-4)
8955     *  r10 = call index
8956     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8957     */
8958.LOP_EXECUTE_INLINE_RANGE_continue:
8959    rsb     r0, r0, #4                  @ r0<- 4-r0
8960    FETCH(r9, 2)                        @ r9<- CCCC
8961    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8962    bl      common_abort                @ (skipped due to ARM prefetch)
89634:  add     ip, r9, #3                  @ base+3
8964    GET_VREG(r3, ip)                    @ r3<- vBase[3]
89653:  add     ip, r9, #2                  @ base+2
8966    GET_VREG(r2, ip)                    @ r2<- vBase[2]
89672:  add     ip, r9, #1                  @ base+1
8968    GET_VREG(r1, ip)                    @ r1<- vBase[1]
89691:  add     ip, r9, #0                  @ (nop)
8970    GET_VREG(r0, ip)                    @ r0<- vBase[0]
89710:
8972    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
8973    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8974    @ (not reached)
8975
8976.LOP_EXECUTE_INLINE_RANGE_table:
8977    .word   gDvmInlineOpsTable
8978
8979
8980    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8981    .global dvmAsmSisterEnd
8982dvmAsmSisterEnd:
8983
8984/* File: armv5te/footer.S */
8985
8986/*
8987 * ===========================================================================
8988 *  Common subroutines and data
8989 * ===========================================================================
8990 */
8991
8992
8993
8994    .text
8995    .align  2
8996
8997#if defined(WITH_JIT)
8998#if defined(WITH_SELF_VERIFICATION)
8999    .global dvmJitToInterpPunt
9000dvmJitToInterpPunt:
9001    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9002    b      dvmJitSelfVerificationEnd    @ doesn't return
9003
9004    .global dvmJitToInterpSingleStep
9005dvmJitToInterpSingleStep:
9006    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9007    b      dvmJitSelfVerificationEnd    @ doesn't return
9008
9009    .global dvmJitToTraceSelect
9010dvmJitToTraceSelect:
9011    ldr    r0,[lr, #-1]                 @ pass our target PC
9012    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9013    b      dvmJitSelfVerificationEnd    @ doesn't return
9014
9015    .global dvmJitToBackwardBranch
9016dvmJitToBackwardBranch:
9017    ldr    r0,[lr, #-1]                 @ pass our target PC
9018    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9019    b      dvmJitSelfVerificationEnd    @ doesn't return
9020
9021    .global dvmJitToInterpNormal
9022dvmJitToInterpNormal:
9023    ldr    r0,[lr, #-1]                 @ pass our target PC
9024    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9025    b      dvmJitSelfVerificationEnd    @ doesn't return
9026
9027    .global dvmJitToInterpNoChain
9028dvmJitToInterpNoChain:
9029    mov    r0,rPC                       @ pass our target PC
9030    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9031    b      dvmJitSelfVerificationEnd    @ doesn't return
9032#else
9033/*
9034 * Return from the translation cache to the interpreter when the compiler is
9035 * having issues translating/executing a Dalvik instruction. We have to skip
9036 * the code cache lookup otherwise it is possible to indefinitely bouce
9037 * between the interpreter and the code cache if the instruction that fails
9038 * to be compiled happens to be at a trace start.
9039 */
9040    .global dvmJitToInterpPunt
9041dvmJitToInterpPunt:
9042    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9043    mov    rPC, r0
9044#ifdef EXIT_STATS
9045    mov    r0,lr
9046    bl     dvmBumpPunt;
9047#endif
9048    EXPORT_PC()
9049    mov    r0, #0
9050    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9051    adrl   rIBASE, dvmAsmInstructionStart
9052    FETCH_INST()
9053    GET_INST_OPCODE(ip)
9054    GOTO_OPCODE(ip)
9055
9056/*
9057 * Return to the interpreter to handle a single instruction.
9058 * On entry:
9059 *    r0 <= PC
9060 *    r1 <= PC of resume instruction
9061 *    lr <= resume point in translation
9062 */
9063    .global dvmJitToInterpSingleStep
9064dvmJitToInterpSingleStep:
9065    str    lr,[rGLUE,#offGlue_jitResume]
9066    str    r1,[rGLUE,#offGlue_jitResumePC]
9067    mov    r1,#kInterpEntryInstr
9068    @ enum is 4 byte in aapcs-EABI
9069    str    r1, [rGLUE, #offGlue_entryPoint]
9070    mov    rPC,r0
9071    EXPORT_PC()
9072
9073    adrl   rIBASE, dvmAsmInstructionStart
9074    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9075    str    r2,[rGLUE,#offGlue_jitState]
9076    mov    r1,#1                  @ set changeInterp to bail to debug interp
9077    b      common_gotoBail
9078
9079
9080/*
9081 * Return from the translation cache and immediately request
9082 * a translation for the exit target.  Commonly used following
9083 * invokes.
9084 */
9085    .global dvmJitToTraceSelect
9086dvmJitToTraceSelect:
9087    ldr    rPC,[lr, #-1]           @ get our target PC
9088    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9089    add    rINST,lr,#-5            @ save start of chain branch
9090    mov    r0,rPC
9091    bl     dvmJitGetCodeAddr       @ Is there a translation?
9092    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9093    cmp    r0,#0
9094    beq    2f
9095    mov    r1,rINST
9096    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9097    mov    r1, rPC                  @ arg1 of translation may need this
9098    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9099    cmp    r0,#0                    @ successful chain?
9100    bxne   r0                       @ continue native execution
9101    b      toInterpreter            @ didn't chain - resume with interpreter
9102
9103/* No translation, so request one if profiling isn't disabled*/
91042:
9105    adrl   rIBASE, dvmAsmInstructionStart
9106    GET_JIT_PROF_TABLE(r0)
9107    FETCH_INST()
9108    cmp    r0, #0
9109    bne    common_selectTrace
9110    GET_INST_OPCODE(ip)
9111    GOTO_OPCODE(ip)
9112
9113/*
9114 * Return from the translation cache to the interpreter.
9115 * The return was done with a BLX from thumb mode, and
9116 * the following 32-bit word contains the target rPC value.
9117 * Note that lr (r14) will have its low-order bit set to denote
9118 * its thumb-mode origin.
9119 *
9120 * We'll need to stash our lr origin away, recover the new
9121 * target and then check to see if there is a translation available
9122 * for our new target.  If so, we do a translation chain and
9123 * go back to native execution.  Otherwise, it's back to the
9124 * interpreter (after treating this entry as a potential
9125 * trace start).
9126 */
9127    .global dvmJitToInterpNormal
9128dvmJitToInterpNormal:
9129    ldr    rPC,[lr, #-1]           @ get our target PC
9130    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9131    add    rINST,lr,#-5            @ save start of chain branch
9132#ifdef EXIT_STATS
9133    bl     dvmBumpNormal
9134#endif
9135    mov    r0,rPC
9136    bl     dvmJitGetCodeAddr        @ Is there a translation?
9137    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9138    cmp    r0,#0
9139    beq    toInterpreter            @ go if not, otherwise do chain
9140    mov    r1,rINST
9141    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9142    mov    r1, rPC                  @ arg1 of translation may need this
9143    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9144    cmp    r0,#0                    @ successful chain?
9145    bxne   r0                       @ continue native execution
9146    b      toInterpreter            @ didn't chain - resume with interpreter
9147
9148/*
9149 * Return from the translation cache to the interpreter to do method invocation.
9150 * Check if translation exists for the callee, but don't chain to it.
9151 */
9152    .global dvmJitToInterpNoChain
9153dvmJitToInterpNoChain:
9154#ifdef EXIT_STATS
9155    bl     dvmBumpNoChain
9156#endif
9157    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9158    mov    r0,rPC
9159    bl     dvmJitGetCodeAddr        @ Is there a translation?
9160    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9161    mov    r1, rPC                  @ arg1 of translation may need this
9162    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9163    cmp    r0,#0
9164    bxne   r0                       @ continue native execution if so
9165#endif
9166
9167/*
9168 * No translation, restore interpreter regs and start interpreting.
9169 * rGLUE & rFP were preserved in the translated code, and rPC has
9170 * already been restored by the time we get here.  We'll need to set
9171 * up rIBASE & rINST, and load the address of the JitTable into r0.
9172 */
9173toInterpreter:
9174    EXPORT_PC()
9175    adrl   rIBASE, dvmAsmInstructionStart
9176    FETCH_INST()
9177    GET_JIT_PROF_TABLE(r0)
9178    @ NOTE: intended fallthrough
9179/*
9180 * Common code to update potential trace start counter, and initiate
9181 * a trace-build if appropriate.  On entry, rPC should point to the
9182 * next instruction to execute, and rINST should be already loaded with
9183 * the next opcode word, and r0 holds a pointer to the jit profile
9184 * table (pJitProfTable).
9185 */
9186common_testUpdateProfile:
9187    cmp     r0,#0
9188    GET_INST_OPCODE(ip)
9189    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9190
9191common_updateProfile:
9192    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9193    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9194    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9195    GET_INST_OPCODE(ip)
9196    subs    r1,r1,#1           @ decrement counter
9197    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9198    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9199
9200/*
9201 * Here, we switch to the debug interpreter to request
9202 * trace selection.  First, though, check to see if there
9203 * is already a native translation in place (and, if so,
9204 * jump to it now).
9205 */
9206    GET_JIT_THRESHOLD(r1)
9207    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9208    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9209    EXPORT_PC()
9210    mov     r0,rPC
9211    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9212    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9213    mov     r1, rPC                     @ arg1 of translation may need this
9214    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9215    cmp     r0,#0
9216#if !defined(WITH_SELF_VERIFICATION)
9217    bxne    r0                          @ jump to the translation
9218#else
9219    beq     common_selectTrace
9220    /*
9221     * At this point, we have a target translation.  However, if
9222     * that translation is actually the interpret-only pseudo-translation
9223     * we want to treat it the same as no translation.
9224     */
9225    mov     r10, r0                      @ save target
9226    bl      dvmCompilerGetInterpretTemplate
9227    cmp     r0, r10                      @ special case?
9228    bne     dvmJitSelfVerificationStart  @ set up self verification
9229    GET_INST_OPCODE(ip)
9230    GOTO_OPCODE(ip)
9231    /* no return */
9232#endif
9233
9234common_selectTrace:
9235    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9236    str     r2,[rGLUE,#offGlue_jitState]
9237    mov     r2,#kInterpEntryInstr       @ normal entry reason
9238    str     r2,[rGLUE,#offGlue_entryPoint]
9239    mov     r1,#1                       @ set changeInterp
9240    b       common_gotoBail
9241
9242#if defined(WITH_SELF_VERIFICATION)
9243/*
9244 * Save PC and registers to shadow memory for self verification mode
9245 * before jumping to native translation.
9246 * On entry, r10 contains the address of the target translation.
9247 */
9248dvmJitSelfVerificationStart:
9249    mov     r0,rPC                      @ r0<- program counter
9250    mov     r1,rFP                      @ r1<- frame pointer
9251    mov     r2,rGLUE                    @ r2<- InterpState pointer
9252    mov     r3,r10                      @ r3<- target translation
9253    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9254    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9255    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9256    bx      r10                         @ jump to the translation
9257
9258/*
9259 * Restore PC, registers, and interpState to original values
9260 * before jumping back to the interpreter.
9261 */
9262dvmJitSelfVerificationEnd:
9263    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9264    mov    r1, #0
9265    str    r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9266    mov    r1,rFP                        @ pass ending fp
9267    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9268    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9269    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9270    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9271    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9272    cmp    r1,#0                         @ check for punt condition
9273    beq    1f
9274    mov    r2,#kJitSelfVerification      @ ask for self verification
9275    str    r2,[rGLUE,#offGlue_jitState]
9276    mov    r2,#kInterpEntryInstr         @ normal entry reason
9277    str    r2,[rGLUE,#offGlue_entryPoint]
9278    mov    r1,#1                         @ set changeInterp
9279    b      common_gotoBail
9280
92811:                                       @ exit to interpreter without check
9282    EXPORT_PC()
9283    adrl   rIBASE, dvmAsmInstructionStart
9284    FETCH_INST()
9285    GET_INST_OPCODE(ip)
9286    GOTO_OPCODE(ip)
9287#endif
9288
9289#endif
9290
9291/*
9292 * Common code when a backward branch is taken.
9293 *
9294 * On entry:
9295 *  r9 is PC adjustment *in bytes*
9296 */
9297common_backwardBranch:
9298    mov     r0, #kInterpEntryInstr
9299    bl      common_periodicChecks
9300#if defined(WITH_JIT)
9301    GET_JIT_PROF_TABLE(r0)
9302    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9303    cmp     r0,#0
9304    bne     common_updateProfile
9305    GET_INST_OPCODE(ip)
9306    GOTO_OPCODE(ip)
9307#else
9308    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9309    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9310    GOTO_OPCODE(ip)                     @ jump to next instruction
9311#endif
9312
9313
9314/*
9315 * Need to see if the thread needs to be suspended or debugger/profiler
9316 * activity has begun.
9317 *
9318 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9319 * have to do the second ldr.
9320 *
9321 * TODO: reduce this so we're just checking a single location.
9322 *
9323 * On entry:
9324 *  r0 is reentry type, e.g. kInterpEntryInstr
9325 *  r9 is trampoline PC adjustment *in bytes*
9326 */
9327common_periodicChecks:
9328    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9329
9330    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9331    str     r0, [rGLUE, #offGlue_entryPoint]
9332
9333#if defined(WITH_DEBUGGER)
9334    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9335#endif
9336#if defined(WITH_PROFILER)
9337    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9338#endif
9339
9340    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9341
9342#if defined(WITH_DEBUGGER)
9343    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9344#endif
9345#if defined (WITH_PROFILER)
9346    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9347#endif
9348
9349    cmp     r3, #0                      @ suspend pending?
9350    bne     2f                          @ yes, do full suspension check
9351
9352#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9353# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9354    orrs    r1, r1, r2                  @ r1<- r1 | r2
9355    cmp     r1, #0                      @ debugger attached or profiler started?
9356# elif defined(WITH_DEBUGGER)
9357    cmp     r1, #0                      @ debugger attached?
9358# elif defined(WITH_PROFILER)
9359    cmp     r2, #0                      @ profiler started?
9360# endif
9361    bne     3f                          @ debugger/profiler, switch interp
9362#endif
9363
9364    bx      lr                          @ nothing to do, return
9365
93662:  @ check suspend
9367#if defined(WITH_JIT)
9368    /*
9369     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9370     * doubles as the Jit's on/off switch.
9371     */
9372    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable
9373    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9374    ldr     r3, [r3] @ r10 <- pJitProfTable
9375    EXPORT_PC()                         @ need for precise GC
9376    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9377#else
9378    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9379    EXPORT_PC()                         @ need for precise GC
9380#endif
9381    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9382
93833:  @ debugger/profiler enabled, bail out
9384    add     rPC, rPC, r9                @ update rPC
9385    mov     r1, #1                      @ "want switch" = true
9386    b       common_gotoBail
9387
9388
9389/*
9390 * The equivalent of "goto bail", this calls through the "bail handler".
9391 *
9392 * State registers will be saved to the "glue" area before bailing.
9393 *
9394 * On entry:
9395 *  r1 is "bool changeInterp", indicating if we want to switch to the
9396 *     other interpreter or just bail all the way out
9397 */
9398common_gotoBail:
9399    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9400    mov     r0, rGLUE                   @ r0<- glue ptr
9401    b       dvmMterpStdBail             @ call(glue, changeInterp)
9402
9403    @add     r1, r1, #1                  @ using (boolean+1)
9404    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9405    @bl      _longjmp                    @ does not return
9406    @bl      common_abort
9407
9408
9409/*
9410 * Common code for method invocation with range.
9411 *
9412 * On entry:
9413 *  r0 is "Method* methodToCall", the method we're trying to call
9414 */
9415common_invokeMethodRange:
9416.LinvokeNewRange:
9417    @ prepare to copy args to "outs" area of current frame
9418    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9419    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9420    beq     .LinvokeArgsDone            @ if no args, skip the rest
9421    FETCH(r1, 2)                        @ r1<- CCCC
9422
9423    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9424    @ (very few methods have > 10 args; could unroll for common cases)
9425    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9426    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9427    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94281:  ldr     r1, [r3], #4                @ val = *fp++
9429    subs    r2, r2, #1                  @ count--
9430    str     r1, [r10], #4               @ *outs++ = val
9431    bne     1b                          @ ...while count != 0
9432    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9433    b       .LinvokeArgsDone
9434
9435/*
9436 * Common code for method invocation without range.
9437 *
9438 * On entry:
9439 *  r0 is "Method* methodToCall", the method we're trying to call
9440 */
9441common_invokeMethodNoRange:
9442.LinvokeNewNoRange:
9443    @ prepare to copy args to "outs" area of current frame
9444    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9445    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9446    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9447    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9448    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9449    beq     .LinvokeArgsDone
9450
9451    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9452.LinvokeNonRange:
9453    rsb     r2, r2, #5                  @ r2<- 5-r2
9454    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9455    bl      common_abort                @ (skipped due to ARM prefetch)
94565:  and     ip, rINST, #0x0f00          @ isolate A
9457    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9458    mov     r0, r0                      @ nop
9459    str     r2, [r10, #-4]!             @ *--outs = vA
94604:  and     ip, r1, #0xf000             @ isolate G
9461    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9462    mov     r0, r0                      @ nop
9463    str     r2, [r10, #-4]!             @ *--outs = vG
94643:  and     ip, r1, #0x0f00             @ isolate F
9465    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9466    mov     r0, r0                      @ nop
9467    str     r2, [r10, #-4]!             @ *--outs = vF
94682:  and     ip, r1, #0x00f0             @ isolate E
9469    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9470    mov     r0, r0                      @ nop
9471    str     r2, [r10, #-4]!             @ *--outs = vE
94721:  and     ip, r1, #0x000f             @ isolate D
9473    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9474    mov     r0, r0                      @ nop
9475    str     r2, [r10, #-4]!             @ *--outs = vD
94760:  @ fall through to .LinvokeArgsDone
9477
9478.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9479    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9480    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9481    @ find space for the new stack frame, check for overflow
9482    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9483    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9484    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9485@    bl      common_dumpRegs
9486    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9487    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9488    cmp     r3, r9                      @ bottom < interpStackEnd?
9489    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9490    blt     .LstackOverflow             @ yes, this frame will overflow stack
9491
9492    @ set up newSaveArea
9493#ifdef EASY_GDB
9494    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9495    str     ip, [r10, #offStackSaveArea_prevSave]
9496#endif
9497    str     rFP, [r10, #offStackSaveArea_prevFrame]
9498    str     rPC, [r10, #offStackSaveArea_savedPc]
9499#if defined(WITH_JIT)
9500    mov     r9, #0
9501    str     r9, [r10, #offStackSaveArea_returnAddr]
9502#endif
9503    str     r0, [r10, #offStackSaveArea_method]
9504    tst     r3, #ACC_NATIVE
9505    bne     .LinvokeNative
9506
9507    /*
9508    stmfd   sp!, {r0-r3}
9509    bl      common_printNewline
9510    mov     r0, rFP
9511    mov     r1, #0
9512    bl      dvmDumpFp
9513    ldmfd   sp!, {r0-r3}
9514    stmfd   sp!, {r0-r3}
9515    mov     r0, r1
9516    mov     r1, r10
9517    bl      dvmDumpFp
9518    bl      common_printNewline
9519    ldmfd   sp!, {r0-r3}
9520    */
9521
9522    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9523    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9524    mov     rPC, r2                         @ publish new rPC
9525    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9526
9527    @ Update "glue" values for the new method
9528    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9529    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9530    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9531#if defined(WITH_JIT)
9532    GET_JIT_PROF_TABLE(r0)
9533    mov     rFP, r1                         @ fp = newFp
9534    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9535    mov     rINST, r9                       @ publish new rINST
9536    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9537    cmp     r0,#0
9538    bne     common_updateProfile
9539    GOTO_OPCODE(ip)                         @ jump to next instruction
9540#else
9541    mov     rFP, r1                         @ fp = newFp
9542    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9543    mov     rINST, r9                       @ publish new rINST
9544    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9545    GOTO_OPCODE(ip)                         @ jump to next instruction
9546#endif
9547
9548.LinvokeNative:
9549    @ Prep for the native call
9550    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9551    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9552    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9553    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9554    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9555    mov     r9, r3                      @ r9<- glue->self (preserve)
9556
9557    mov     r2, r0                      @ r2<- methodToCall
9558    mov     r0, r1                      @ r0<- newFp (points to args)
9559    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9560
9561#ifdef ASSIST_DEBUGGER
9562    /* insert fake function header to help gdb find the stack frame */
9563    b       .Lskip
9564    .type   dalvik_mterp, %function
9565dalvik_mterp:
9566    .fnstart
9567    MTERP_ENTRY1
9568    MTERP_ENTRY2
9569.Lskip:
9570#endif
9571
9572    @mov     lr, pc                      @ set return addr
9573    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9574    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9575
9576#if defined(WITH_JIT)
9577    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9578#endif
9579
9580    @ native return; r9=self, r10=newSaveArea
9581    @ equivalent to dvmPopJniLocals
9582    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9583    ldr     r1, [r9, #offThread_exception] @ check for exception
9584#if defined(WITH_JIT)
9585    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9586#endif
9587    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9588    cmp     r1, #0                      @ null?
9589    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9590#if defined(WITH_JIT)
9591    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9592#endif
9593    bne     common_exceptionThrown      @ no, handle exception
9594
9595    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9596    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9597    GOTO_OPCODE(ip)                     @ jump to next instruction
9598
9599.LstackOverflow:    @ r0=methodToCall
9600    mov     r1, r0                      @ r1<- methodToCall
9601    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9602    bl      dvmHandleStackOverflow
9603    b       common_exceptionThrown
9604#ifdef ASSIST_DEBUGGER
9605    .fnend
9606#endif
9607
9608
9609    /*
9610     * Common code for method invocation, calling through "glue code".
9611     *
9612     * TODO: now that we have range and non-range invoke handlers, this
9613     *       needs to be split into two.  Maybe just create entry points
9614     *       that set r9 and jump here?
9615     *
9616     * On entry:
9617     *  r0 is "Method* methodToCall", the method we're trying to call
9618     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9619     */
9620     .if    0
9621.LinvokeOld:
9622    sub     sp, sp, #8                  @ space for args + pad
9623    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9624    mov     r2, r0                      @ A2<- methodToCall
9625    mov     r0, rGLUE                   @ A0<- glue
9626    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9627    mov     r1, r9                      @ A1<- methodCallRange
9628    mov     r3, rINST, lsr #8           @ A3<- AA
9629    str     ip, [sp, #0]                @ A4<- ip
9630    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9631    add     sp, sp, #8                  @ remove arg area
9632    b       common_resumeAfterGlueCall  @ continue to next instruction
9633    .endif
9634
9635
9636
9637/*
9638 * Common code for handling a return instruction.
9639 *
9640 * This does not return.
9641 */
9642common_returnFromMethod:
9643.LreturnNew:
9644    mov     r0, #kInterpEntryReturn
9645    mov     r9, #0
9646    bl      common_periodicChecks
9647
9648    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9649    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9650    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9651    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9652                                        @ r2<- method we're returning to
9653    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9654    cmp     r2, #0                      @ is this a break frame?
9655    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9656    mov     r1, #0                      @ "want switch" = false
9657    beq     common_gotoBail             @ break frame, bail out completely
9658
9659    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9660    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9661    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9662    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9663#if defined(WITH_JIT)
9664    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
9665    GET_JIT_PROF_TABLE(r0)
9666    mov     rPC, r9                     @ publish new rPC
9667    str     r1, [rGLUE, #offGlue_methodClassDex]
9668    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
9669    cmp     r10, #0                      @ caller is compiled code
9670    blxne   r10
9671    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9672    cmp     r0,#0
9673    bne     common_updateProfile
9674    GOTO_OPCODE(ip)                     @ jump to next instruction
9675#else
9676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9677    mov     rPC, r9                     @ publish new rPC
9678    str     r1, [rGLUE, #offGlue_methodClassDex]
9679    GOTO_OPCODE(ip)                     @ jump to next instruction
9680#endif
9681
9682    /*
9683     * Return handling, calls through "glue code".
9684     */
9685     .if    0
9686.LreturnOld:
9687    SAVE_PC_FP_TO_GLUE()                @ export state
9688    mov     r0, rGLUE                   @ arg to function
9689    bl      dvmMterp_returnFromMethod
9690    b       common_resumeAfterGlueCall
9691    .endif
9692
9693
9694/*
9695 * Somebody has thrown an exception.  Handle it.
9696 *
9697 * If the exception processing code returns to us (instead of falling
9698 * out of the interpreter), continue with whatever the next instruction
9699 * now happens to be.
9700 *
9701 * This does not return.
9702 */
9703     .global dvmMterpCommonExceptionThrown
9704dvmMterpCommonExceptionThrown:
9705common_exceptionThrown:
9706.LexceptionNew:
9707    mov     r0, #kInterpEntryThrow
9708    mov     r9, #0
9709    bl      common_periodicChecks
9710
9711#if defined(WITH_JIT)
9712    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
9713    str     r2,[rGLUE,#offGlue_jitState]
9714#endif
9715
9716    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9717    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9718    mov     r1, r10                     @ r1<- self
9719    mov     r0, r9                      @ r0<- exception
9720    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9721    mov     r3, #0                      @ r3<- NULL
9722    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9723
9724    /* set up args and a local for "&fp" */
9725    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9726    str     rFP, [sp, #-4]!             @ *--sp = fp
9727    mov     ip, sp                      @ ip<- &fp
9728    mov     r3, #0                      @ r3<- false
9729    str     ip, [sp, #-4]!              @ *--sp = &fp
9730    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9731    mov     r0, r10                     @ r0<- self
9732    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9733    mov     r2, r9                      @ r2<- exception
9734    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9735    mov     r1, r1, asr #1              @ r1<- offset in code units
9736
9737    /* call, r0 gets catchRelPc (a code-unit offset) */
9738    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9739
9740    /* fix earlier stack overflow if necessary; may trash rFP */
9741    ldrb    r1, [r10, #offThread_stackOverflowed]
9742    cmp     r1, #0                      @ did we overflow earlier?
9743    beq     1f                          @ no, skip ahead
9744    mov     rFP, r0                     @ save relPc result in rFP
9745    mov     r0, r10                     @ r0<- self
9746    mov     r1, r9                      @ r1<- exception
9747    bl      dvmCleanupStackOverflow     @ call(self)
9748    mov     r0, rFP                     @ restore result
97491:
9750
9751    /* update frame pointer and check result from dvmFindCatchBlock */
9752    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9753    cmp     r0, #0                      @ is catchRelPc < 0?
9754    add     sp, sp, #8                  @ restore stack
9755    bmi     .LnotCaughtLocally
9756
9757    /* adjust locals to match self->curFrame and updated PC */
9758    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9759    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9760    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9761    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9762    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9763    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9764    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9765    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9766
9767    /* release the tracked alloc on the exception */
9768    mov     r0, r9                      @ r0<- exception
9769    mov     r1, r10                     @ r1<- self
9770    bl      dvmReleaseTrackedAlloc      @ release the exception
9771
9772    /* restore the exception if the handler wants it */
9773    FETCH_INST()                        @ load rINST from rPC
9774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9775    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9776    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9777    GOTO_OPCODE(ip)                     @ jump to next instruction
9778
9779.LnotCaughtLocally: @ r9=exception, r10=self
9780    /* fix stack overflow if necessary */
9781    ldrb    r1, [r10, #offThread_stackOverflowed]
9782    cmp     r1, #0                      @ did we overflow earlier?
9783    movne   r0, r10                     @ if yes: r0<- self
9784    movne   r1, r9                      @ if yes: r1<- exception
9785    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9786
9787    @ may want to show "not caught locally" debug messages here
9788#if DVM_SHOW_EXCEPTION >= 2
9789    /* call __android_log_print(prio, tag, format, ...) */
9790    /* "Exception %s from %s:%d not caught locally" */
9791    @ dvmLineNumFromPC(method, pc - method->insns)
9792    ldr     r0, [rGLUE, #offGlue_method]
9793    ldr     r1, [r0, #offMethod_insns]
9794    sub     r1, rPC, r1
9795    asr     r1, r1, #1
9796    bl      dvmLineNumFromPC
9797    str     r0, [sp, #-4]!
9798    @ dvmGetMethodSourceFile(method)
9799    ldr     r0, [rGLUE, #offGlue_method]
9800    bl      dvmGetMethodSourceFile
9801    str     r0, [sp, #-4]!
9802    @ exception->clazz->descriptor
9803    ldr     r3, [r9, #offObject_clazz]
9804    ldr     r3, [r3, #offClassObject_descriptor]
9805    @
9806    ldr     r2, strExceptionNotCaughtLocally
9807    ldr     r1, strLogTag
9808    mov     r0, #3                      @ LOG_DEBUG
9809    bl      __android_log_print
9810#endif
9811    str     r9, [r10, #offThread_exception] @ restore exception
9812    mov     r0, r9                      @ r0<- exception
9813    mov     r1, r10                     @ r1<- self
9814    bl      dvmReleaseTrackedAlloc      @ release the exception
9815    mov     r1, #0                      @ "want switch" = false
9816    b       common_gotoBail             @ bail out
9817
9818
9819    /*
9820     * Exception handling, calls through "glue code".
9821     */
9822    .if     0
9823.LexceptionOld:
9824    SAVE_PC_FP_TO_GLUE()                @ export state
9825    mov     r0, rGLUE                   @ arg to function
9826    bl      dvmMterp_exceptionThrown
9827    b       common_resumeAfterGlueCall
9828    .endif
9829
9830
9831/*
9832 * After returning from a "glued" function, pull out the updated
9833 * values and start executing at the next instruction.
9834 */
9835common_resumeAfterGlueCall:
9836    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9837    FETCH_INST()                        @ load rINST from rPC
9838    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9839    GOTO_OPCODE(ip)                     @ jump to next instruction
9840
9841/*
9842 * Invalid array index.
9843 */
9844common_errArrayIndex:
9845    EXPORT_PC()
9846    ldr     r0, strArrayIndexException
9847    mov     r1, #0
9848    bl      dvmThrowException
9849    b       common_exceptionThrown
9850
9851/*
9852 * Invalid array value.
9853 */
9854common_errArrayStore:
9855    EXPORT_PC()
9856    ldr     r0, strArrayStoreException
9857    mov     r1, #0
9858    bl      dvmThrowException
9859    b       common_exceptionThrown
9860
9861/*
9862 * Integer divide or mod by zero.
9863 */
9864common_errDivideByZero:
9865    EXPORT_PC()
9866    ldr     r0, strArithmeticException
9867    ldr     r1, strDivideByZero
9868    bl      dvmThrowException
9869    b       common_exceptionThrown
9870
9871/*
9872 * Attempt to allocate an array with a negative size.
9873 */
9874common_errNegativeArraySize:
9875    EXPORT_PC()
9876    ldr     r0, strNegativeArraySizeException
9877    mov     r1, #0
9878    bl      dvmThrowException
9879    b       common_exceptionThrown
9880
9881/*
9882 * Invocation of a non-existent method.
9883 */
9884common_errNoSuchMethod:
9885    EXPORT_PC()
9886    ldr     r0, strNoSuchMethodError
9887    mov     r1, #0
9888    bl      dvmThrowException
9889    b       common_exceptionThrown
9890
9891/*
9892 * We encountered a null object when we weren't expecting one.  We
9893 * export the PC, throw a NullPointerException, and goto the exception
9894 * processing code.
9895 */
9896common_errNullObject:
9897    EXPORT_PC()
9898    ldr     r0, strNullPointerException
9899    mov     r1, #0
9900    bl      dvmThrowException
9901    b       common_exceptionThrown
9902
9903/*
9904 * For debugging, cause an immediate fault.  The source address will
9905 * be in lr (use a bl instruction to jump here).
9906 */
9907common_abort:
9908    ldr     pc, .LdeadFood
9909.LdeadFood:
9910    .word   0xdeadf00d
9911
9912/*
9913 * Spit out a "we were here", preserving all registers.  (The attempt
9914 * to save ip won't work, but we need to save an even number of
9915 * registers for EABI 64-bit stack alignment.)
9916 */
9917    .macro  SQUEAK num
9918common_squeak\num:
9919    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9920    ldr     r0, strSqueak
9921    mov     r1, #\num
9922    bl      printf
9923    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9924    bx      lr
9925    .endm
9926
9927    SQUEAK  0
9928    SQUEAK  1
9929    SQUEAK  2
9930    SQUEAK  3
9931    SQUEAK  4
9932    SQUEAK  5
9933
9934/*
9935 * Spit out the number in r0, preserving registers.
9936 */
9937common_printNum:
9938    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9939    mov     r1, r0
9940    ldr     r0, strSqueak
9941    bl      printf
9942    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9943    bx      lr
9944
9945/*
9946 * Print a newline, preserving registers.
9947 */
9948common_printNewline:
9949    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9950    ldr     r0, strNewline
9951    bl      printf
9952    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9953    bx      lr
9954
9955    /*
9956     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9957     */
9958common_printHex:
9959    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9960    mov     r1, r0
9961    ldr     r0, strPrintHex
9962    bl      printf
9963    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9964    bx      lr
9965
9966/*
9967 * Print the 64-bit quantity in r0-r1, preserving registers.
9968 */
9969common_printLong:
9970    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9971    mov     r3, r1
9972    mov     r2, r0
9973    ldr     r0, strPrintLong
9974    bl      printf
9975    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9976    bx      lr
9977
9978/*
9979 * Print full method info.  Pass the Method* in r0.  Preserves regs.
9980 */
9981common_printMethod:
9982    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9983    bl      dvmMterpPrintMethod
9984    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9985    bx      lr
9986
9987/*
9988 * Call a C helper function that dumps regs and possibly some
9989 * additional info.  Requires the C function to be compiled in.
9990 */
9991    .if     0
9992common_dumpRegs:
9993    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9994    bl      dvmMterpDumpArmRegs
9995    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9996    bx      lr
9997    .endif
9998
9999#if 0
10000/*
10001 * Experiment on VFP mode.
10002 *
10003 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10004 *
10005 * Updates the bits specified by "mask", setting them to the values in "val".
10006 */
10007setFPSCR:
10008    and     r0, r0, r1                  @ make sure no stray bits are set
10009    fmrx    r2, fpscr                   @ get VFP reg
10010    mvn     r1, r1                      @ bit-invert mask
10011    and     r2, r2, r1                  @ clear masked bits
10012    orr     r2, r2, r0                  @ set specified bits
10013    fmxr    fpscr, r2                   @ set VFP reg
10014    mov     r0, r2                      @ return new value
10015    bx      lr
10016
10017    .align  2
10018    .global dvmConfigureFP
10019    .type   dvmConfigureFP, %function
10020dvmConfigureFP:
10021    stmfd   sp!, {ip, lr}
10022    /* 0x03000000 sets DN/FZ */
10023    /* 0x00009f00 clears the six exception enable flags */
10024    bl      common_squeak0
10025    mov     r0, #0x03000000             @ r0<- 0x03000000
10026    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10027    bl      setFPSCR
10028    ldmfd   sp!, {ip, pc}
10029#endif
10030
10031
10032/*
10033 * String references, must be close to the code that uses them.
10034 */
10035    .align  2
10036strArithmeticException:
10037    .word   .LstrArithmeticException
10038strArrayIndexException:
10039    .word   .LstrArrayIndexException
10040strArrayStoreException:
10041    .word   .LstrArrayStoreException
10042strDivideByZero:
10043    .word   .LstrDivideByZero
10044strNegativeArraySizeException:
10045    .word   .LstrNegativeArraySizeException
10046strNoSuchMethodError:
10047    .word   .LstrNoSuchMethodError
10048strNullPointerException:
10049    .word   .LstrNullPointerException
10050
10051strLogTag:
10052    .word   .LstrLogTag
10053strExceptionNotCaughtLocally:
10054    .word   .LstrExceptionNotCaughtLocally
10055
10056strNewline:
10057    .word   .LstrNewline
10058strSqueak:
10059    .word   .LstrSqueak
10060strPrintHex:
10061    .word   .LstrPrintHex
10062strPrintLong:
10063    .word   .LstrPrintLong
10064
10065/*
10066 * Zero-terminated ASCII string data.
10067 *
10068 * On ARM we have two choices: do like gcc does, and LDR from a .word
10069 * with the address, or use an ADR pseudo-op to get the address
10070 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10071 * PC-relative addressing mode and hence has a limited range, which
10072 * makes it not work well with mergeable string sections.
10073 */
10074    .section .rodata.str1.4,"aMS",%progbits,1
10075
10076.LstrBadEntryPoint:
10077    .asciz  "Bad entry point %d\n"
10078.LstrArithmeticException:
10079    .asciz  "Ljava/lang/ArithmeticException;"
10080.LstrArrayIndexException:
10081    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10082.LstrArrayStoreException:
10083    .asciz  "Ljava/lang/ArrayStoreException;"
10084.LstrClassCastException:
10085    .asciz  "Ljava/lang/ClassCastException;"
10086.LstrDivideByZero:
10087    .asciz  "divide by zero"
10088.LstrFilledNewArrayNotImpl:
10089    .asciz  "filled-new-array only implemented for objects and 'int'"
10090.LstrInternalError:
10091    .asciz  "Ljava/lang/InternalError;"
10092.LstrInstantiationError:
10093    .asciz  "Ljava/lang/InstantiationError;"
10094.LstrNegativeArraySizeException:
10095    .asciz  "Ljava/lang/NegativeArraySizeException;"
10096.LstrNoSuchMethodError:
10097    .asciz  "Ljava/lang/NoSuchMethodError;"
10098.LstrNullPointerException:
10099    .asciz  "Ljava/lang/NullPointerException;"
10100
10101.LstrLogTag:
10102    .asciz  "mterp"
10103.LstrExceptionNotCaughtLocally:
10104    .asciz  "Exception %s from %s:%d not caught locally\n"
10105
10106.LstrNewline:
10107    .asciz  "\n"
10108.LstrSqueak:
10109    .asciz  "<%d>"
10110.LstrPrintHex:
10111    .asciz  "<0x%x>"
10112.LstrPrintLong:
10113    .asciz  "<%lld>"
10114
10115
10116