InterpAsm-armv7-a.S revision 51ae442fa9ed49e081e58e5127d1805789dbb196
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    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
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    str     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     1f                          @ 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    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
913    beq     common_exceptionThrown      @ yes, exception is pending
914    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
915    GOTO_OPCODE(ip)                     @ jump to next instruction
9161:
917    FETCH_ADVANCE_INST(1)               @ advance before throw
918    b      common_errNullObject
919
920
921/* ------------------------------ */
922    .balign 64
923.L_OP_CHECK_CAST: /* 0x1f */
924/* File: armv5te/OP_CHECK_CAST.S */
925    /*
926     * Check to see if a cast from one class to another is allowed.
927     */
928    /* check-cast vAA, class@BBBB */
929    mov     r3, rINST, lsr #8           @ r3<- AA
930    FETCH(r2, 1)                        @ r2<- BBBB
931    GET_VREG(r9, r3)                    @ r9<- object
932    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
933    cmp     r9, #0                      @ is object null?
934    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
935    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
936    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
937    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
938    cmp     r1, #0                      @ have we resolved this before?
939    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
940.LOP_CHECK_CAST_resolved:
941    cmp     r0, r1                      @ same class (trivial success)?
942    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
943.LOP_CHECK_CAST_okay:
944    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
946    GOTO_OPCODE(ip)                     @ jump to next instruction
947
948/* ------------------------------ */
949    .balign 64
950.L_OP_INSTANCE_OF: /* 0x20 */
951/* File: armv5te/OP_INSTANCE_OF.S */
952    /*
953     * Check to see if an object reference is an instance of a class.
954     *
955     * Most common situation is a non-null object, being compared against
956     * an already-resolved class.
957     */
958    /* instance-of vA, vB, class@CCCC */
959    mov     r3, rINST, lsr #12          @ r3<- B
960    mov     r9, rINST, lsr #8           @ r9<- A+
961    GET_VREG(r0, r3)                    @ r0<- vB (object)
962    and     r9, r9, #15                 @ r9<- A
963    cmp     r0, #0                      @ is object null?
964    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
965    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
966    FETCH(r3, 1)                        @ r3<- CCCC
967    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
968    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
969    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
970    cmp     r1, #0                      @ have we resolved this before?
971    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
972.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
973    cmp     r0, r1                      @ same class (trivial success)?
974    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
975    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
976
977/* ------------------------------ */
978    .balign 64
979.L_OP_ARRAY_LENGTH: /* 0x21 */
980/* File: armv6t2/OP_ARRAY_LENGTH.S */
981    /*
982     * Return the length of an array.
983     */
984    mov     r1, rINST, lsr #12          @ r1<- B
985    ubfx    r2, rINST, #8, #4           @ r2<- A
986    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
987    cmp     r0, #0                      @ is object null?
988    beq     common_errNullObject        @ yup, fail
989    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
990    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
991    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
992    SET_VREG(r3, r2)                    @ vB<- length
993    GOTO_OPCODE(ip)                     @ jump to next instruction
994
995
996/* ------------------------------ */
997    .balign 64
998.L_OP_NEW_INSTANCE: /* 0x22 */
999/* File: armv5te/OP_NEW_INSTANCE.S */
1000    /*
1001     * Create a new instance of a class.
1002     */
1003    /* new-instance vAA, class@BBBB */
1004    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1005    FETCH(r1, 1)                        @ r1<- BBBB
1006    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1007    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1008    EXPORT_PC()                         @ req'd for init, resolve, alloc
1009    cmp     r0, #0                      @ already resolved?
1010    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1011.LOP_NEW_INSTANCE_resolved:   @ r0=class
1012    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1013    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1014    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1015.LOP_NEW_INSTANCE_initialized: @ r0=class
1016    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1017    bl      dvmAllocObject              @ r0<- new object
1018    b       .LOP_NEW_INSTANCE_finish          @ continue
1019
1020/* ------------------------------ */
1021    .balign 64
1022.L_OP_NEW_ARRAY: /* 0x23 */
1023/* File: armv5te/OP_NEW_ARRAY.S */
1024    /*
1025     * Allocate an array of objects, specified with the array class
1026     * and a count.
1027     *
1028     * The verifier guarantees that this is an array class, so we don't
1029     * check for it here.
1030     */
1031    /* new-array vA, vB, class@CCCC */
1032    mov     r0, rINST, lsr #12          @ r0<- B
1033    FETCH(r2, 1)                        @ r2<- CCCC
1034    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1035    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1036    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1037    cmp     r1, #0                      @ check length
1038    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1039    bmi     common_errNegativeArraySize @ negative length, bail
1040    cmp     r0, #0                      @ already resolved?
1041    EXPORT_PC()                         @ req'd for resolve, alloc
1042    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1043    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1044
1045/* ------------------------------ */
1046    .balign 64
1047.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1048/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1049    /*
1050     * Create a new array with elements filled from registers.
1051     *
1052     * for: filled-new-array, filled-new-array/range
1053     */
1054    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1055    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1056    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1057    FETCH(r1, 1)                        @ r1<- BBBB
1058    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1059    EXPORT_PC()                         @ need for resolve and alloc
1060    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1061    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1062    cmp     r0, #0                      @ already resolved?
1063    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10648:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1065    mov     r2, #0                      @ r2<- false
1066    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1067    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1068    cmp     r0, #0                      @ got null?
1069    beq     common_exceptionThrown      @ yes, handle exception
1070    b       .LOP_FILLED_NEW_ARRAY_continue
1071
1072/* ------------------------------ */
1073    .balign 64
1074.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1075/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1076/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1077    /*
1078     * Create a new array with elements filled from registers.
1079     *
1080     * for: filled-new-array, filled-new-array/range
1081     */
1082    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1083    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1084    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1085    FETCH(r1, 1)                        @ r1<- BBBB
1086    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1087    EXPORT_PC()                         @ need for resolve and alloc
1088    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1089    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1090    cmp     r0, #0                      @ already resolved?
1091    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10928:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1093    mov     r2, #0                      @ r2<- false
1094    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1095    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1096    cmp     r0, #0                      @ got null?
1097    beq     common_exceptionThrown      @ yes, handle exception
1098    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1099
1100
1101/* ------------------------------ */
1102    .balign 64
1103.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1104/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1105    /* fill-array-data vAA, +BBBBBBBB */
1106    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1107    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1108    mov     r3, rINST, lsr #8           @ r3<- AA
1109    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1110    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1111    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1112    EXPORT_PC();
1113    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1114    cmp     r0, #0                      @ 0 means an exception is thrown
1115    beq     common_exceptionThrown      @ has exception
1116    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1117    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1118    GOTO_OPCODE(ip)                     @ jump to next instruction
1119
1120/* ------------------------------ */
1121    .balign 64
1122.L_OP_THROW: /* 0x27 */
1123/* File: armv5te/OP_THROW.S */
1124    /*
1125     * Throw an exception object in the current thread.
1126     */
1127    /* throw vAA */
1128    mov     r2, rINST, lsr #8           @ r2<- AA
1129    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1130    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1131    cmp     r1, #0                      @ null object?
1132    beq     common_errNullObject        @ yes, throw an NPE instead
1133    @ bypass dvmSetException, just store it
1134    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1135    b       common_exceptionThrown
1136
1137
1138/* ------------------------------ */
1139    .balign 64
1140.L_OP_GOTO: /* 0x28 */
1141/* File: armv5te/OP_GOTO.S */
1142    /*
1143     * Unconditional branch, 8-bit offset.
1144     *
1145     * The branch distance is a signed code-unit offset, which we need to
1146     * double to get a byte offset.
1147     */
1148    /* goto +AA */
1149    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1150    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1151    mov     r9, r9, lsl #1              @ r9<- byte offset
1152    bmi     common_backwardBranch       @ backward branch, do periodic checks
1153#if defined(WITH_JIT)
1154    GET_JIT_PROF_TABLE(r0)
1155    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1156    cmp     r0,#0
1157    bne     common_updateProfile
1158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1159    GOTO_OPCODE(ip)                     @ jump to next instruction
1160#else
1161    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1162    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1163    GOTO_OPCODE(ip)                     @ jump to next instruction
1164#endif
1165
1166/* ------------------------------ */
1167    .balign 64
1168.L_OP_GOTO_16: /* 0x29 */
1169/* File: armv5te/OP_GOTO_16.S */
1170    /*
1171     * Unconditional branch, 16-bit offset.
1172     *
1173     * The branch distance is a signed code-unit offset, which we need to
1174     * double to get a byte offset.
1175     */
1176    /* goto/16 +AAAA */
1177    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1178    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1179    bmi     common_backwardBranch       @ backward branch, do periodic checks
1180#if defined(WITH_JIT)
1181    GET_JIT_PROF_TABLE(r0)
1182    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1183    cmp     r0,#0
1184    bne     common_updateProfile
1185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1186    GOTO_OPCODE(ip)                     @ jump to next instruction
1187#else
1188    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1190    GOTO_OPCODE(ip)                     @ jump to next instruction
1191#endif
1192
1193
1194/* ------------------------------ */
1195    .balign 64
1196.L_OP_GOTO_32: /* 0x2a */
1197/* File: armv5te/OP_GOTO_32.S */
1198    /*
1199     * Unconditional branch, 32-bit offset.
1200     *
1201     * The branch distance is a signed code-unit offset, which we need to
1202     * double to get a byte offset.
1203     *
1204     * Unlike most opcodes, this one is allowed to branch to itself, so
1205     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1206     * instruction doesn't affect the V flag, so we need to clear it
1207     * explicitly.
1208     */
1209    /* goto/32 +AAAAAAAA */
1210    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1211    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1212    cmp     ip, ip                      @ (clear V flag during stall)
1213    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1214    mov     r9, r0, asl #1              @ r9<- byte offset
1215    ble     common_backwardBranch       @ backward branch, do periodic checks
1216#if defined(WITH_JIT)
1217    GET_JIT_PROF_TABLE(r0)
1218    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1219    cmp     r0,#0
1220    bne     common_updateProfile
1221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1222    GOTO_OPCODE(ip)                     @ jump to next instruction
1223#else
1224    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1226    GOTO_OPCODE(ip)                     @ jump to next instruction
1227#endif
1228
1229/* ------------------------------ */
1230    .balign 64
1231.L_OP_PACKED_SWITCH: /* 0x2b */
1232/* File: armv5te/OP_PACKED_SWITCH.S */
1233    /*
1234     * Handle a packed-switch or sparse-switch instruction.  In both cases
1235     * we decode it and hand it off to a helper function.
1236     *
1237     * We don't really expect backward branches in a switch statement, but
1238     * they're perfectly legal, so we check for them here.
1239     *
1240     * for: packed-switch, sparse-switch
1241     */
1242    /* op vAA, +BBBB */
1243    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1244    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1245    mov     r3, rINST, lsr #8           @ r3<- AA
1246    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1247    GET_VREG(r1, r3)                    @ r1<- vAA
1248    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1249    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1250    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1251    bmi     common_backwardBranch       @ backward branch, do periodic checks
1252    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1253#if defined(WITH_JIT)
1254    GET_JIT_PROF_TABLE(r0)
1255    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1256    cmp     r0,#0
1257    bne     common_updateProfile
1258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1259    GOTO_OPCODE(ip)                     @ jump to next instruction
1260#else
1261    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1262    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1263    GOTO_OPCODE(ip)                     @ jump to next instruction
1264#endif
1265
1266
1267/* ------------------------------ */
1268    .balign 64
1269.L_OP_SPARSE_SWITCH: /* 0x2c */
1270/* File: armv5te/OP_SPARSE_SWITCH.S */
1271/* File: armv5te/OP_PACKED_SWITCH.S */
1272    /*
1273     * Handle a packed-switch or sparse-switch instruction.  In both cases
1274     * we decode it and hand it off to a helper function.
1275     *
1276     * We don't really expect backward branches in a switch statement, but
1277     * they're perfectly legal, so we check for them here.
1278     *
1279     * for: packed-switch, sparse-switch
1280     */
1281    /* op vAA, +BBBB */
1282    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1283    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1284    mov     r3, rINST, lsr #8           @ r3<- AA
1285    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1286    GET_VREG(r1, r3)                    @ r1<- vAA
1287    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1288    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1289    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1290    bmi     common_backwardBranch       @ backward branch, do periodic checks
1291    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1292#if defined(WITH_JIT)
1293    GET_JIT_PROF_TABLE(r0)
1294    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1295    cmp     r0,#0
1296    bne     common_updateProfile
1297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1298    GOTO_OPCODE(ip)                     @ jump to next instruction
1299#else
1300    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1301    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1302    GOTO_OPCODE(ip)                     @ jump to next instruction
1303#endif
1304
1305
1306
1307/* ------------------------------ */
1308    .balign 64
1309.L_OP_CMPL_FLOAT: /* 0x2d */
1310/* File: arm-vfp/OP_CMPL_FLOAT.S */
1311    /*
1312     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1313     * destination register based on the results of the comparison.
1314     *
1315     * int compare(x, y) {
1316     *     if (x == y) {
1317     *         return 0;
1318     *     } else if (x > y) {
1319     *         return 1;
1320     *     } else if (x < y) {
1321     *         return -1;
1322     *     } else {
1323     *         return -1;
1324     *     }
1325     * }
1326     */
1327    /* op vAA, vBB, vCC */
1328    FETCH(r0, 1)                        @ r0<- CCBB
1329    mov     r9, rINST, lsr #8           @ r9<- AA
1330    and     r2, r0, #255                @ r2<- BB
1331    mov     r3, r0, lsr #8              @ r3<- CC
1332    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1333    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1334    flds    s0, [r2]                    @ s0<- vBB
1335    flds    s1, [r3]                    @ s1<- vCC
1336    fcmpes  s0, s1                      @ compare (vBB, vCC)
1337    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1338    mvn     r0, #0                      @ r0<- -1 (default)
1339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1340    fmstat                              @ export status flags
1341    movgt   r0, #1                      @ (greater than) r1<- 1
1342    moveq   r0, #0                      @ (equal) r1<- 0
1343    b       .LOP_CMPL_FLOAT_finish          @ argh
1344
1345
1346/* ------------------------------ */
1347    .balign 64
1348.L_OP_CMPG_FLOAT: /* 0x2e */
1349/* File: arm-vfp/OP_CMPG_FLOAT.S */
1350    /*
1351     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1352     * destination register based on the results of the comparison.
1353     *
1354     * int compare(x, y) {
1355     *     if (x == y) {
1356     *         return 0;
1357     *     } else if (x < y) {
1358     *         return -1;
1359     *     } else if (x > y) {
1360     *         return 1;
1361     *     } else {
1362     *         return 1;
1363     *     }
1364     * }
1365     */
1366    /* op vAA, vBB, vCC */
1367    FETCH(r0, 1)                        @ r0<- CCBB
1368    mov     r9, rINST, lsr #8           @ r9<- AA
1369    and     r2, r0, #255                @ r2<- BB
1370    mov     r3, r0, lsr #8              @ r3<- CC
1371    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1372    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1373    flds    s0, [r2]                    @ s0<- vBB
1374    flds    s1, [r3]                    @ s1<- vCC
1375    fcmpes  s0, s1                      @ compare (vBB, vCC)
1376    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1377    mov     r0, #1                      @ r0<- 1 (default)
1378    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1379    fmstat                              @ export status flags
1380    mvnmi   r0, #0                      @ (less than) r1<- -1
1381    moveq   r0, #0                      @ (equal) r1<- 0
1382    b       .LOP_CMPG_FLOAT_finish          @ argh
1383
1384
1385/* ------------------------------ */
1386    .balign 64
1387.L_OP_CMPL_DOUBLE: /* 0x2f */
1388/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1389    /*
1390     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1391     * destination register based on the results of the comparison.
1392     *
1393     * int compare(x, y) {
1394     *     if (x == y) {
1395     *         return 0;
1396     *     } else if (x > y) {
1397     *         return 1;
1398     *     } else if (x < y) {
1399     *         return -1;
1400     *     } else {
1401     *         return -1;
1402     *     }
1403     * }
1404     */
1405    /* op vAA, vBB, vCC */
1406    FETCH(r0, 1)                        @ r0<- CCBB
1407    mov     r9, rINST, lsr #8           @ r9<- AA
1408    and     r2, r0, #255                @ r2<- BB
1409    mov     r3, r0, lsr #8              @ r3<- CC
1410    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1411    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1412    fldd    d0, [r2]                    @ d0<- vBB
1413    fldd    d1, [r3]                    @ d1<- vCC
1414    fcmped  d0, d1                      @ compare (vBB, vCC)
1415    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1416    mvn     r0, #0                      @ r0<- -1 (default)
1417    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1418    fmstat                              @ export status flags
1419    movgt   r0, #1                      @ (greater than) r1<- 1
1420    moveq   r0, #0                      @ (equal) r1<- 0
1421    b       .LOP_CMPL_DOUBLE_finish          @ argh
1422
1423
1424/* ------------------------------ */
1425    .balign 64
1426.L_OP_CMPG_DOUBLE: /* 0x30 */
1427/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1428    /*
1429     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1430     * destination register based on the results of the comparison.
1431     *
1432     * int compare(x, y) {
1433     *     if (x == y) {
1434     *         return 0;
1435     *     } else if (x < y) {
1436     *         return -1;
1437     *     } else if (x > y) {
1438     *         return 1;
1439     *     } else {
1440     *         return 1;
1441     *     }
1442     * }
1443     */
1444    /* op vAA, vBB, vCC */
1445    FETCH(r0, 1)                        @ r0<- CCBB
1446    mov     r9, rINST, lsr #8           @ r9<- AA
1447    and     r2, r0, #255                @ r2<- BB
1448    mov     r3, r0, lsr #8              @ r3<- CC
1449    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1450    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1451    fldd    d0, [r2]                    @ d0<- vBB
1452    fldd    d1, [r3]                    @ d1<- vCC
1453    fcmped  d0, d1                      @ compare (vBB, vCC)
1454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1455    mov     r0, #1                      @ r0<- 1 (default)
1456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1457    fmstat                              @ export status flags
1458    mvnmi   r0, #0                      @ (less than) r1<- -1
1459    moveq   r0, #0                      @ (equal) r1<- 0
1460    b       .LOP_CMPG_DOUBLE_finish          @ argh
1461
1462
1463/* ------------------------------ */
1464    .balign 64
1465.L_OP_CMP_LONG: /* 0x31 */
1466/* File: armv5te/OP_CMP_LONG.S */
1467    /*
1468     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1469     * register based on the results of the comparison.
1470     *
1471     * We load the full values with LDM, but in practice many values could
1472     * be resolved by only looking at the high word.  This could be made
1473     * faster or slower by splitting the LDM into a pair of LDRs.
1474     *
1475     * If we just wanted to set condition flags, we could do this:
1476     *  subs    ip, r0, r2
1477     *  sbcs    ip, r1, r3
1478     *  subeqs  ip, r0, r2
1479     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1480     * integer value, which we can do with 2 conditional mov/mvn instructions
1481     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1482     * us a constant 5-cycle path plus a branch at the end to the
1483     * instruction epilogue code.  The multi-compare approach below needs
1484     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1485     * in the worst case (the 64-bit values are equal).
1486     */
1487    /* cmp-long vAA, vBB, vCC */
1488    FETCH(r0, 1)                        @ r0<- CCBB
1489    mov     r9, rINST, lsr #8           @ r9<- AA
1490    and     r2, r0, #255                @ r2<- BB
1491    mov     r3, r0, lsr #8              @ r3<- CC
1492    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1493    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1494    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1495    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1496    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1497    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1498    bgt     .LOP_CMP_LONG_greater
1499    subs    r1, r0, r2                  @ r1<- r0 - r2
1500    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1501    bne     .LOP_CMP_LONG_less
1502    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1503
1504/* ------------------------------ */
1505    .balign 64
1506.L_OP_IF_EQ: /* 0x32 */
1507/* File: armv6t2/OP_IF_EQ.S */
1508/* File: armv6t2/bincmp.S */
1509    /*
1510     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1511     * fragment that specifies the *reverse* comparison to perform, e.g.
1512     * for "if-le" you would use "gt".
1513     *
1514     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1515     */
1516    /* if-cmp vA, vB, +CCCC */
1517    mov     r1, rINST, lsr #12          @ r1<- B
1518    ubfx    r0, rINST, #8, #4           @ r0<- A
1519    GET_VREG(r3, r1)                    @ r3<- vB
1520    GET_VREG(r2, r0)                    @ r2<- vA
1521    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1522    cmp     r2, r3                      @ compare (vA, vB)
1523    bne  1f                      @ branch to 1 if comparison failed
1524    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1525    movs    r9, r9, asl #1              @ convert to bytes, check sign
1526    bmi     common_backwardBranch       @ yes, do periodic checks
15271:
1528#if defined(WITH_JIT)
1529    GET_JIT_PROF_TABLE(r0)
1530    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1531    b        common_testUpdateProfile
1532#else
1533    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1534    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1535    GOTO_OPCODE(ip)                     @ jump to next instruction
1536#endif
1537
1538
1539
1540/* ------------------------------ */
1541    .balign 64
1542.L_OP_IF_NE: /* 0x33 */
1543/* File: armv6t2/OP_IF_NE.S */
1544/* File: armv6t2/bincmp.S */
1545    /*
1546     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1547     * fragment that specifies the *reverse* comparison to perform, e.g.
1548     * for "if-le" you would use "gt".
1549     *
1550     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1551     */
1552    /* if-cmp vA, vB, +CCCC */
1553    mov     r1, rINST, lsr #12          @ r1<- B
1554    ubfx    r0, rINST, #8, #4           @ r0<- A
1555    GET_VREG(r3, r1)                    @ r3<- vB
1556    GET_VREG(r2, r0)                    @ r2<- vA
1557    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1558    cmp     r2, r3                      @ compare (vA, vB)
1559    beq  1f                      @ branch to 1 if comparison failed
1560    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1561    movs    r9, r9, asl #1              @ convert to bytes, check sign
1562    bmi     common_backwardBranch       @ yes, do periodic checks
15631:
1564#if defined(WITH_JIT)
1565    GET_JIT_PROF_TABLE(r0)
1566    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1567    b        common_testUpdateProfile
1568#else
1569    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1571    GOTO_OPCODE(ip)                     @ jump to next instruction
1572#endif
1573
1574
1575
1576/* ------------------------------ */
1577    .balign 64
1578.L_OP_IF_LT: /* 0x34 */
1579/* File: armv6t2/OP_IF_LT.S */
1580/* File: armv6t2/bincmp.S */
1581    /*
1582     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1583     * fragment that specifies the *reverse* comparison to perform, e.g.
1584     * for "if-le" you would use "gt".
1585     *
1586     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1587     */
1588    /* if-cmp vA, vB, +CCCC */
1589    mov     r1, rINST, lsr #12          @ r1<- B
1590    ubfx    r0, rINST, #8, #4           @ r0<- A
1591    GET_VREG(r3, r1)                    @ r3<- vB
1592    GET_VREG(r2, r0)                    @ r2<- vA
1593    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1594    cmp     r2, r3                      @ compare (vA, vB)
1595    bge  1f                      @ branch to 1 if comparison failed
1596    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1597    movs    r9, r9, asl #1              @ convert to bytes, check sign
1598    bmi     common_backwardBranch       @ yes, do periodic checks
15991:
1600#if defined(WITH_JIT)
1601    GET_JIT_PROF_TABLE(r0)
1602    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1603    b        common_testUpdateProfile
1604#else
1605    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1606    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1607    GOTO_OPCODE(ip)                     @ jump to next instruction
1608#endif
1609
1610
1611
1612/* ------------------------------ */
1613    .balign 64
1614.L_OP_IF_GE: /* 0x35 */
1615/* File: armv6t2/OP_IF_GE.S */
1616/* File: armv6t2/bincmp.S */
1617    /*
1618     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1619     * fragment that specifies the *reverse* comparison to perform, e.g.
1620     * for "if-le" you would use "gt".
1621     *
1622     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1623     */
1624    /* if-cmp vA, vB, +CCCC */
1625    mov     r1, rINST, lsr #12          @ r1<- B
1626    ubfx    r0, rINST, #8, #4           @ r0<- A
1627    GET_VREG(r3, r1)                    @ r3<- vB
1628    GET_VREG(r2, r0)                    @ r2<- vA
1629    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1630    cmp     r2, r3                      @ compare (vA, vB)
1631    blt  1f                      @ branch to 1 if comparison failed
1632    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1633    movs    r9, r9, asl #1              @ convert to bytes, check sign
1634    bmi     common_backwardBranch       @ yes, do periodic checks
16351:
1636#if defined(WITH_JIT)
1637    GET_JIT_PROF_TABLE(r0)
1638    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1639    b        common_testUpdateProfile
1640#else
1641    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1642    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1643    GOTO_OPCODE(ip)                     @ jump to next instruction
1644#endif
1645
1646
1647
1648/* ------------------------------ */
1649    .balign 64
1650.L_OP_IF_GT: /* 0x36 */
1651/* File: armv6t2/OP_IF_GT.S */
1652/* File: armv6t2/bincmp.S */
1653    /*
1654     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1655     * fragment that specifies the *reverse* comparison to perform, e.g.
1656     * for "if-le" you would use "gt".
1657     *
1658     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1659     */
1660    /* if-cmp vA, vB, +CCCC */
1661    mov     r1, rINST, lsr #12          @ r1<- B
1662    ubfx    r0, rINST, #8, #4           @ r0<- A
1663    GET_VREG(r3, r1)                    @ r3<- vB
1664    GET_VREG(r2, r0)                    @ r2<- vA
1665    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1666    cmp     r2, r3                      @ compare (vA, vB)
1667    ble  1f                      @ branch to 1 if comparison failed
1668    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1669    movs    r9, r9, asl #1              @ convert to bytes, check sign
1670    bmi     common_backwardBranch       @ yes, do periodic checks
16711:
1672#if defined(WITH_JIT)
1673    GET_JIT_PROF_TABLE(r0)
1674    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1675    b        common_testUpdateProfile
1676#else
1677    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1678    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1679    GOTO_OPCODE(ip)                     @ jump to next instruction
1680#endif
1681
1682
1683
1684/* ------------------------------ */
1685    .balign 64
1686.L_OP_IF_LE: /* 0x37 */
1687/* File: armv6t2/OP_IF_LE.S */
1688/* File: armv6t2/bincmp.S */
1689    /*
1690     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1691     * fragment that specifies the *reverse* comparison to perform, e.g.
1692     * for "if-le" you would use "gt".
1693     *
1694     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1695     */
1696    /* if-cmp vA, vB, +CCCC */
1697    mov     r1, rINST, lsr #12          @ r1<- B
1698    ubfx    r0, rINST, #8, #4           @ r0<- A
1699    GET_VREG(r3, r1)                    @ r3<- vB
1700    GET_VREG(r2, r0)                    @ r2<- vA
1701    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1702    cmp     r2, r3                      @ compare (vA, vB)
1703    bgt  1f                      @ branch to 1 if comparison failed
1704    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1705    movs    r9, r9, asl #1              @ convert to bytes, check sign
1706    bmi     common_backwardBranch       @ yes, do periodic checks
17071:
1708#if defined(WITH_JIT)
1709    GET_JIT_PROF_TABLE(r0)
1710    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1711    b        common_testUpdateProfile
1712#else
1713    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1714    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1715    GOTO_OPCODE(ip)                     @ jump to next instruction
1716#endif
1717
1718
1719
1720/* ------------------------------ */
1721    .balign 64
1722.L_OP_IF_EQZ: /* 0x38 */
1723/* File: armv5te/OP_IF_EQZ.S */
1724/* File: armv5te/zcmp.S */
1725    /*
1726     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1727     * fragment that specifies the *reverse* comparison to perform, e.g.
1728     * for "if-le" you would use "gt".
1729     *
1730     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1731     */
1732    /* if-cmp vAA, +BBBB */
1733    mov     r0, rINST, lsr #8           @ r0<- AA
1734    GET_VREG(r2, r0)                    @ r2<- vAA
1735    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1736    cmp     r2, #0                      @ compare (vA, 0)
1737    bne  1f                      @ branch to 1 if comparison failed
1738    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1739    movs    r9, r9, asl #1              @ convert to bytes, check sign
1740    bmi     common_backwardBranch       @ backward branch, do periodic checks
17411:
1742#if defined(WITH_JIT)
1743    GET_JIT_PROF_TABLE(r0)
1744    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1745    cmp     r0,#0
1746    bne     common_updateProfile
1747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1748    GOTO_OPCODE(ip)                     @ jump to next instruction
1749#else
1750    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1752    GOTO_OPCODE(ip)                     @ jump to next instruction
1753#endif
1754
1755
1756
1757/* ------------------------------ */
1758    .balign 64
1759.L_OP_IF_NEZ: /* 0x39 */
1760/* File: armv5te/OP_IF_NEZ.S */
1761/* File: armv5te/zcmp.S */
1762    /*
1763     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1764     * fragment that specifies the *reverse* comparison to perform, e.g.
1765     * for "if-le" you would use "gt".
1766     *
1767     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1768     */
1769    /* if-cmp vAA, +BBBB */
1770    mov     r0, rINST, lsr #8           @ r0<- AA
1771    GET_VREG(r2, r0)                    @ r2<- vAA
1772    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1773    cmp     r2, #0                      @ compare (vA, 0)
1774    beq  1f                      @ branch to 1 if comparison failed
1775    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1776    movs    r9, r9, asl #1              @ convert to bytes, check sign
1777    bmi     common_backwardBranch       @ backward branch, do periodic checks
17781:
1779#if defined(WITH_JIT)
1780    GET_JIT_PROF_TABLE(r0)
1781    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1782    cmp     r0,#0
1783    bne     common_updateProfile
1784    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1785    GOTO_OPCODE(ip)                     @ jump to next instruction
1786#else
1787    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1789    GOTO_OPCODE(ip)                     @ jump to next instruction
1790#endif
1791
1792
1793
1794/* ------------------------------ */
1795    .balign 64
1796.L_OP_IF_LTZ: /* 0x3a */
1797/* File: armv5te/OP_IF_LTZ.S */
1798/* File: armv5te/zcmp.S */
1799    /*
1800     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1801     * fragment that specifies the *reverse* comparison to perform, e.g.
1802     * for "if-le" you would use "gt".
1803     *
1804     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1805     */
1806    /* if-cmp vAA, +BBBB */
1807    mov     r0, rINST, lsr #8           @ r0<- AA
1808    GET_VREG(r2, r0)                    @ r2<- vAA
1809    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1810    cmp     r2, #0                      @ compare (vA, 0)
1811    bge  1f                      @ branch to 1 if comparison failed
1812    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1813    movs    r9, r9, asl #1              @ convert to bytes, check sign
1814    bmi     common_backwardBranch       @ backward branch, do periodic checks
18151:
1816#if defined(WITH_JIT)
1817    GET_JIT_PROF_TABLE(r0)
1818    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1819    cmp     r0,#0
1820    bne     common_updateProfile
1821    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1822    GOTO_OPCODE(ip)                     @ jump to next instruction
1823#else
1824    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1825    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1826    GOTO_OPCODE(ip)                     @ jump to next instruction
1827#endif
1828
1829
1830
1831/* ------------------------------ */
1832    .balign 64
1833.L_OP_IF_GEZ: /* 0x3b */
1834/* File: armv5te/OP_IF_GEZ.S */
1835/* File: armv5te/zcmp.S */
1836    /*
1837     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1838     * fragment that specifies the *reverse* comparison to perform, e.g.
1839     * for "if-le" you would use "gt".
1840     *
1841     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1842     */
1843    /* if-cmp vAA, +BBBB */
1844    mov     r0, rINST, lsr #8           @ r0<- AA
1845    GET_VREG(r2, r0)                    @ r2<- vAA
1846    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1847    cmp     r2, #0                      @ compare (vA, 0)
1848    blt  1f                      @ branch to 1 if comparison failed
1849    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1850    movs    r9, r9, asl #1              @ convert to bytes, check sign
1851    bmi     common_backwardBranch       @ backward branch, do periodic checks
18521:
1853#if defined(WITH_JIT)
1854    GET_JIT_PROF_TABLE(r0)
1855    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1856    cmp     r0,#0
1857    bne     common_updateProfile
1858    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1859    GOTO_OPCODE(ip)                     @ jump to next instruction
1860#else
1861    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1863    GOTO_OPCODE(ip)                     @ jump to next instruction
1864#endif
1865
1866
1867
1868/* ------------------------------ */
1869    .balign 64
1870.L_OP_IF_GTZ: /* 0x3c */
1871/* File: armv5te/OP_IF_GTZ.S */
1872/* File: armv5te/zcmp.S */
1873    /*
1874     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1875     * fragment that specifies the *reverse* comparison to perform, e.g.
1876     * for "if-le" you would use "gt".
1877     *
1878     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1879     */
1880    /* if-cmp vAA, +BBBB */
1881    mov     r0, rINST, lsr #8           @ r0<- AA
1882    GET_VREG(r2, r0)                    @ r2<- vAA
1883    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1884    cmp     r2, #0                      @ compare (vA, 0)
1885    ble  1f                      @ branch to 1 if comparison failed
1886    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1887    movs    r9, r9, asl #1              @ convert to bytes, check sign
1888    bmi     common_backwardBranch       @ backward branch, do periodic checks
18891:
1890#if defined(WITH_JIT)
1891    GET_JIT_PROF_TABLE(r0)
1892    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1893    cmp     r0,#0
1894    bne     common_updateProfile
1895    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1896    GOTO_OPCODE(ip)                     @ jump to next instruction
1897#else
1898    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1899    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1900    GOTO_OPCODE(ip)                     @ jump to next instruction
1901#endif
1902
1903
1904
1905/* ------------------------------ */
1906    .balign 64
1907.L_OP_IF_LEZ: /* 0x3d */
1908/* File: armv5te/OP_IF_LEZ.S */
1909/* File: armv5te/zcmp.S */
1910    /*
1911     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1912     * fragment that specifies the *reverse* comparison to perform, e.g.
1913     * for "if-le" you would use "gt".
1914     *
1915     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1916     */
1917    /* if-cmp vAA, +BBBB */
1918    mov     r0, rINST, lsr #8           @ r0<- AA
1919    GET_VREG(r2, r0)                    @ r2<- vAA
1920    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1921    cmp     r2, #0                      @ compare (vA, 0)
1922    bgt  1f                      @ branch to 1 if comparison failed
1923    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1924    movs    r9, r9, asl #1              @ convert to bytes, check sign
1925    bmi     common_backwardBranch       @ backward branch, do periodic checks
19261:
1927#if defined(WITH_JIT)
1928    GET_JIT_PROF_TABLE(r0)
1929    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1930    cmp     r0,#0
1931    bne     common_updateProfile
1932    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1933    GOTO_OPCODE(ip)                     @ jump to next instruction
1934#else
1935    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1936    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1937    GOTO_OPCODE(ip)                     @ jump to next instruction
1938#endif
1939
1940
1941
1942/* ------------------------------ */
1943    .balign 64
1944.L_OP_UNUSED_3E: /* 0x3e */
1945/* File: armv5te/OP_UNUSED_3E.S */
1946/* File: armv5te/unused.S */
1947    bl      common_abort
1948
1949
1950
1951/* ------------------------------ */
1952    .balign 64
1953.L_OP_UNUSED_3F: /* 0x3f */
1954/* File: armv5te/OP_UNUSED_3F.S */
1955/* File: armv5te/unused.S */
1956    bl      common_abort
1957
1958
1959
1960/* ------------------------------ */
1961    .balign 64
1962.L_OP_UNUSED_40: /* 0x40 */
1963/* File: armv5te/OP_UNUSED_40.S */
1964/* File: armv5te/unused.S */
1965    bl      common_abort
1966
1967
1968
1969/* ------------------------------ */
1970    .balign 64
1971.L_OP_UNUSED_41: /* 0x41 */
1972/* File: armv5te/OP_UNUSED_41.S */
1973/* File: armv5te/unused.S */
1974    bl      common_abort
1975
1976
1977
1978/* ------------------------------ */
1979    .balign 64
1980.L_OP_UNUSED_42: /* 0x42 */
1981/* File: armv5te/OP_UNUSED_42.S */
1982/* File: armv5te/unused.S */
1983    bl      common_abort
1984
1985
1986
1987/* ------------------------------ */
1988    .balign 64
1989.L_OP_UNUSED_43: /* 0x43 */
1990/* File: armv5te/OP_UNUSED_43.S */
1991/* File: armv5te/unused.S */
1992    bl      common_abort
1993
1994
1995
1996/* ------------------------------ */
1997    .balign 64
1998.L_OP_AGET: /* 0x44 */
1999/* File: armv5te/OP_AGET.S */
2000    /*
2001     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2002     *
2003     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2004     * instructions.  We use a pair of FETCH_Bs instead.
2005     *
2006     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2007     */
2008    /* op vAA, vBB, vCC */
2009    FETCH_B(r2, 1, 0)                   @ r2<- BB
2010    mov     r9, rINST, lsr #8           @ r9<- AA
2011    FETCH_B(r3, 1, 1)                   @ r3<- CC
2012    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2013    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2014    cmp     r0, #0                      @ null array object?
2015    beq     common_errNullObject        @ yes, bail
2016    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2017    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2018    cmp     r1, r3                      @ compare unsigned index, length
2019    bcs     common_errArrayIndex        @ index >= length, bail
2020    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2021    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2022    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2023    SET_VREG(r2, r9)                    @ vAA<- r2
2024    GOTO_OPCODE(ip)                     @ jump to next instruction
2025
2026
2027/* ------------------------------ */
2028    .balign 64
2029.L_OP_AGET_WIDE: /* 0x45 */
2030/* File: armv5te/OP_AGET_WIDE.S */
2031    /*
2032     * Array get, 64 bits.  vAA <- vBB[vCC].
2033     *
2034     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2035     */
2036    /* aget-wide vAA, vBB, vCC */
2037    FETCH(r0, 1)                        @ r0<- CCBB
2038    mov     r9, rINST, lsr #8           @ r9<- AA
2039    and     r2, r0, #255                @ r2<- BB
2040    mov     r3, r0, lsr #8              @ r3<- CC
2041    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2042    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2043    cmp     r0, #0                      @ null array object?
2044    beq     common_errNullObject        @ yes, bail
2045    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2046    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2047    cmp     r1, r3                      @ compare unsigned index, length
2048    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2049    b       common_errArrayIndex        @ index >= length, bail
2050    @ May want to swap the order of these two branches depending on how the
2051    @ branch prediction (if any) handles conditional forward branches vs.
2052    @ unconditional forward branches.
2053
2054/* ------------------------------ */
2055    .balign 64
2056.L_OP_AGET_OBJECT: /* 0x46 */
2057/* File: armv5te/OP_AGET_OBJECT.S */
2058/* File: armv5te/OP_AGET.S */
2059    /*
2060     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2061     *
2062     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2063     * instructions.  We use a pair of FETCH_Bs instead.
2064     *
2065     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2066     */
2067    /* op vAA, vBB, vCC */
2068    FETCH_B(r2, 1, 0)                   @ r2<- BB
2069    mov     r9, rINST, lsr #8           @ r9<- AA
2070    FETCH_B(r3, 1, 1)                   @ r3<- CC
2071    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2072    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2073    cmp     r0, #0                      @ null array object?
2074    beq     common_errNullObject        @ yes, bail
2075    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2076    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2077    cmp     r1, r3                      @ compare unsigned index, length
2078    bcs     common_errArrayIndex        @ index >= length, bail
2079    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2080    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2082    SET_VREG(r2, r9)                    @ vAA<- r2
2083    GOTO_OPCODE(ip)                     @ jump to next instruction
2084
2085
2086
2087/* ------------------------------ */
2088    .balign 64
2089.L_OP_AGET_BOOLEAN: /* 0x47 */
2090/* File: armv5te/OP_AGET_BOOLEAN.S */
2091/* File: armv5te/OP_AGET.S */
2092    /*
2093     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2094     *
2095     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2096     * instructions.  We use a pair of FETCH_Bs instead.
2097     *
2098     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2099     */
2100    /* op vAA, vBB, vCC */
2101    FETCH_B(r2, 1, 0)                   @ r2<- BB
2102    mov     r9, rINST, lsr #8           @ r9<- AA
2103    FETCH_B(r3, 1, 1)                   @ r3<- CC
2104    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2105    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2106    cmp     r0, #0                      @ null array object?
2107    beq     common_errNullObject        @ yes, bail
2108    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2109    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2110    cmp     r1, r3                      @ compare unsigned index, length
2111    bcs     common_errArrayIndex        @ index >= length, bail
2112    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2113    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2115    SET_VREG(r2, r9)                    @ vAA<- r2
2116    GOTO_OPCODE(ip)                     @ jump to next instruction
2117
2118
2119
2120/* ------------------------------ */
2121    .balign 64
2122.L_OP_AGET_BYTE: /* 0x48 */
2123/* File: armv5te/OP_AGET_BYTE.S */
2124/* File: armv5te/OP_AGET.S */
2125    /*
2126     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2127     *
2128     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2129     * instructions.  We use a pair of FETCH_Bs instead.
2130     *
2131     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2132     */
2133    /* op vAA, vBB, vCC */
2134    FETCH_B(r2, 1, 0)                   @ r2<- BB
2135    mov     r9, rINST, lsr #8           @ r9<- AA
2136    FETCH_B(r3, 1, 1)                   @ r3<- CC
2137    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2138    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2139    cmp     r0, #0                      @ null array object?
2140    beq     common_errNullObject        @ yes, bail
2141    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2142    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2143    cmp     r1, r3                      @ compare unsigned index, length
2144    bcs     common_errArrayIndex        @ index >= length, bail
2145    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2146    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2148    SET_VREG(r2, r9)                    @ vAA<- r2
2149    GOTO_OPCODE(ip)                     @ jump to next instruction
2150
2151
2152
2153/* ------------------------------ */
2154    .balign 64
2155.L_OP_AGET_CHAR: /* 0x49 */
2156/* File: armv5te/OP_AGET_CHAR.S */
2157/* File: armv5te/OP_AGET.S */
2158    /*
2159     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2160     *
2161     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2162     * instructions.  We use a pair of FETCH_Bs instead.
2163     *
2164     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2165     */
2166    /* op vAA, vBB, vCC */
2167    FETCH_B(r2, 1, 0)                   @ r2<- BB
2168    mov     r9, rINST, lsr #8           @ r9<- AA
2169    FETCH_B(r3, 1, 1)                   @ r3<- CC
2170    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2171    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2172    cmp     r0, #0                      @ null array object?
2173    beq     common_errNullObject        @ yes, bail
2174    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2175    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2176    cmp     r1, r3                      @ compare unsigned index, length
2177    bcs     common_errArrayIndex        @ index >= length, bail
2178    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2179    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2180    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2181    SET_VREG(r2, r9)                    @ vAA<- r2
2182    GOTO_OPCODE(ip)                     @ jump to next instruction
2183
2184
2185
2186/* ------------------------------ */
2187    .balign 64
2188.L_OP_AGET_SHORT: /* 0x4a */
2189/* File: armv5te/OP_AGET_SHORT.S */
2190/* File: armv5te/OP_AGET.S */
2191    /*
2192     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2193     *
2194     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2195     * instructions.  We use a pair of FETCH_Bs instead.
2196     *
2197     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2198     */
2199    /* op vAA, vBB, vCC */
2200    FETCH_B(r2, 1, 0)                   @ r2<- BB
2201    mov     r9, rINST, lsr #8           @ r9<- AA
2202    FETCH_B(r3, 1, 1)                   @ r3<- CC
2203    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2204    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2205    cmp     r0, #0                      @ null array object?
2206    beq     common_errNullObject        @ yes, bail
2207    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2208    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2209    cmp     r1, r3                      @ compare unsigned index, length
2210    bcs     common_errArrayIndex        @ index >= length, bail
2211    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2212    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2213    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2214    SET_VREG(r2, r9)                    @ vAA<- r2
2215    GOTO_OPCODE(ip)                     @ jump to next instruction
2216
2217
2218
2219/* ------------------------------ */
2220    .balign 64
2221.L_OP_APUT: /* 0x4b */
2222/* File: armv5te/OP_APUT.S */
2223    /*
2224     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2225     *
2226     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2227     * instructions.  We use a pair of FETCH_Bs instead.
2228     *
2229     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2230     */
2231    /* op vAA, vBB, vCC */
2232    FETCH_B(r2, 1, 0)                   @ r2<- BB
2233    mov     r9, rINST, lsr #8           @ r9<- AA
2234    FETCH_B(r3, 1, 1)                   @ r3<- CC
2235    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2236    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2237    cmp     r0, #0                      @ null array object?
2238    beq     common_errNullObject        @ yes, bail
2239    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2240    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2241    cmp     r1, r3                      @ compare unsigned index, length
2242    bcs     common_errArrayIndex        @ index >= length, bail
2243    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2244    GET_VREG(r2, r9)                    @ r2<- vAA
2245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2246    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2247    GOTO_OPCODE(ip)                     @ jump to next instruction
2248
2249
2250/* ------------------------------ */
2251    .balign 64
2252.L_OP_APUT_WIDE: /* 0x4c */
2253/* File: armv5te/OP_APUT_WIDE.S */
2254    /*
2255     * Array put, 64 bits.  vBB[vCC] <- vAA.
2256     *
2257     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2258     */
2259    /* aput-wide vAA, vBB, vCC */
2260    FETCH(r0, 1)                        @ r0<- CCBB
2261    mov     r9, rINST, lsr #8           @ r9<- AA
2262    and     r2, r0, #255                @ r2<- BB
2263    mov     r3, r0, lsr #8              @ r3<- CC
2264    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2265    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2266    cmp     r0, #0                      @ null array object?
2267    beq     common_errNullObject        @ yes, bail
2268    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2269    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2270    cmp     r1, r3                      @ compare unsigned index, length
2271    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2272    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2273    b       common_errArrayIndex        @ index >= length, bail
2274    @ May want to swap the order of these two branches depending on how the
2275    @ branch prediction (if any) handles conditional forward branches vs.
2276    @ unconditional forward branches.
2277
2278/* ------------------------------ */
2279    .balign 64
2280.L_OP_APUT_OBJECT: /* 0x4d */
2281/* File: armv5te/OP_APUT_OBJECT.S */
2282    /*
2283     * Store an object into an array.  vBB[vCC] <- vAA.
2284     *
2285     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2286     * instructions.  We use a pair of FETCH_Bs instead.
2287     */
2288    /* op vAA, vBB, vCC */
2289    FETCH(r0, 1)                        @ r0<- CCBB
2290    mov     r9, rINST, lsr #8           @ r9<- AA
2291    and     r2, r0, #255                @ r2<- BB
2292    mov     r3, r0, lsr #8              @ r3<- CC
2293    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2294    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2295    cmp     r1, #0                      @ null array object?
2296    GET_VREG(r9, r9)                    @ r9<- vAA
2297    beq     common_errNullObject        @ yes, bail
2298    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2299    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2300    cmp     r0, r3                      @ compare unsigned index, length
2301    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2302    b       common_errArrayIndex        @ index >= length, bail
2303
2304
2305/* ------------------------------ */
2306    .balign 64
2307.L_OP_APUT_BOOLEAN: /* 0x4e */
2308/* File: armv5te/OP_APUT_BOOLEAN.S */
2309/* File: armv5te/OP_APUT.S */
2310    /*
2311     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2312     *
2313     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2314     * instructions.  We use a pair of FETCH_Bs instead.
2315     *
2316     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2317     */
2318    /* op vAA, vBB, vCC */
2319    FETCH_B(r2, 1, 0)                   @ r2<- BB
2320    mov     r9, rINST, lsr #8           @ r9<- AA
2321    FETCH_B(r3, 1, 1)                   @ r3<- CC
2322    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2323    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2324    cmp     r0, #0                      @ null array object?
2325    beq     common_errNullObject        @ yes, bail
2326    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2327    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2328    cmp     r1, r3                      @ compare unsigned index, length
2329    bcs     common_errArrayIndex        @ index >= length, bail
2330    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2331    GET_VREG(r2, r9)                    @ r2<- vAA
2332    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2333    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2334    GOTO_OPCODE(ip)                     @ jump to next instruction
2335
2336
2337
2338/* ------------------------------ */
2339    .balign 64
2340.L_OP_APUT_BYTE: /* 0x4f */
2341/* File: armv5te/OP_APUT_BYTE.S */
2342/* File: armv5te/OP_APUT.S */
2343    /*
2344     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2345     *
2346     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2347     * instructions.  We use a pair of FETCH_Bs instead.
2348     *
2349     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2350     */
2351    /* op vAA, vBB, vCC */
2352    FETCH_B(r2, 1, 0)                   @ r2<- BB
2353    mov     r9, rINST, lsr #8           @ r9<- AA
2354    FETCH_B(r3, 1, 1)                   @ r3<- CC
2355    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2356    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2357    cmp     r0, #0                      @ null array object?
2358    beq     common_errNullObject        @ yes, bail
2359    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2360    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2361    cmp     r1, r3                      @ compare unsigned index, length
2362    bcs     common_errArrayIndex        @ index >= length, bail
2363    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2364    GET_VREG(r2, r9)                    @ r2<- vAA
2365    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2366    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2367    GOTO_OPCODE(ip)                     @ jump to next instruction
2368
2369
2370
2371/* ------------------------------ */
2372    .balign 64
2373.L_OP_APUT_CHAR: /* 0x50 */
2374/* File: armv5te/OP_APUT_CHAR.S */
2375/* File: armv5te/OP_APUT.S */
2376    /*
2377     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2378     *
2379     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2380     * instructions.  We use a pair of FETCH_Bs instead.
2381     *
2382     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2383     */
2384    /* op vAA, vBB, vCC */
2385    FETCH_B(r2, 1, 0)                   @ r2<- BB
2386    mov     r9, rINST, lsr #8           @ r9<- AA
2387    FETCH_B(r3, 1, 1)                   @ r3<- CC
2388    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2389    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2390    cmp     r0, #0                      @ null array object?
2391    beq     common_errNullObject        @ yes, bail
2392    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2393    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2394    cmp     r1, r3                      @ compare unsigned index, length
2395    bcs     common_errArrayIndex        @ index >= length, bail
2396    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2397    GET_VREG(r2, r9)                    @ r2<- vAA
2398    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2399    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2400    GOTO_OPCODE(ip)                     @ jump to next instruction
2401
2402
2403
2404/* ------------------------------ */
2405    .balign 64
2406.L_OP_APUT_SHORT: /* 0x51 */
2407/* File: armv5te/OP_APUT_SHORT.S */
2408/* File: armv5te/OP_APUT.S */
2409    /*
2410     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2411     *
2412     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2413     * instructions.  We use a pair of FETCH_Bs instead.
2414     *
2415     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2416     */
2417    /* op vAA, vBB, vCC */
2418    FETCH_B(r2, 1, 0)                   @ r2<- BB
2419    mov     r9, rINST, lsr #8           @ r9<- AA
2420    FETCH_B(r3, 1, 1)                   @ r3<- CC
2421    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2422    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2423    cmp     r0, #0                      @ null array object?
2424    beq     common_errNullObject        @ yes, bail
2425    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2426    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2427    cmp     r1, r3                      @ compare unsigned index, length
2428    bcs     common_errArrayIndex        @ index >= length, bail
2429    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2430    GET_VREG(r2, r9)                    @ r2<- vAA
2431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2432    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2433    GOTO_OPCODE(ip)                     @ jump to next instruction
2434
2435
2436
2437/* ------------------------------ */
2438    .balign 64
2439.L_OP_IGET: /* 0x52 */
2440/* File: armv6t2/OP_IGET.S */
2441    /*
2442     * General 32-bit instance field get.
2443     *
2444     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2445     */
2446    /* op vA, vB, field@CCCC */
2447    mov     r0, rINST, lsr #12          @ r0<- B
2448    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2449    FETCH(r1, 1)                        @ r1<- field ref CCCC
2450    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2451    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2452    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2453    cmp     r0, #0                      @ is resolved entry null?
2454    bne     .LOP_IGET_finish          @ no, already resolved
24558:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2456    EXPORT_PC()                         @ resolve() could throw
2457    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2458    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2459    cmp     r0, #0
2460    bne     .LOP_IGET_finish
2461    b       common_exceptionThrown
2462
2463/* ------------------------------ */
2464    .balign 64
2465.L_OP_IGET_WIDE: /* 0x53 */
2466/* File: armv6t2/OP_IGET_WIDE.S */
2467    /*
2468     * Wide 32-bit instance field get.
2469     */
2470    /* iget-wide vA, vB, field@CCCC */
2471    mov     r0, rINST, lsr #12          @ r0<- B
2472    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2473    FETCH(r1, 1)                        @ r1<- field ref CCCC
2474    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2475    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2476    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2477    cmp     r0, #0                      @ is resolved entry null?
2478    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24798:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2480    EXPORT_PC()                         @ resolve() could throw
2481    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2482    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2483    cmp     r0, #0
2484    bne     .LOP_IGET_WIDE_finish
2485    b       common_exceptionThrown
2486
2487/* ------------------------------ */
2488    .balign 64
2489.L_OP_IGET_OBJECT: /* 0x54 */
2490/* File: armv5te/OP_IGET_OBJECT.S */
2491/* File: armv5te/OP_IGET.S */
2492    /*
2493     * General 32-bit instance field get.
2494     *
2495     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2496     */
2497    /* op vA, vB, field@CCCC */
2498    mov     r0, rINST, lsr #12          @ r0<- B
2499    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2500    FETCH(r1, 1)                        @ r1<- field ref CCCC
2501    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2502    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2503    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2504    cmp     r0, #0                      @ is resolved entry null?
2505    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
25068:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2507    EXPORT_PC()                         @ resolve() could throw
2508    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2509    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2510    cmp     r0, #0
2511    bne     .LOP_IGET_OBJECT_finish
2512    b       common_exceptionThrown
2513
2514
2515/* ------------------------------ */
2516    .balign 64
2517.L_OP_IGET_BOOLEAN: /* 0x55 */
2518/* File: armv5te/OP_IGET_BOOLEAN.S */
2519@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2520/* File: armv5te/OP_IGET.S */
2521    /*
2522     * General 32-bit instance field get.
2523     *
2524     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2525     */
2526    /* op vA, vB, field@CCCC */
2527    mov     r0, rINST, lsr #12          @ r0<- B
2528    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2529    FETCH(r1, 1)                        @ r1<- field ref CCCC
2530    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2531    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2532    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2533    cmp     r0, #0                      @ is resolved entry null?
2534    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25358:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2536    EXPORT_PC()                         @ resolve() could throw
2537    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2538    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2539    cmp     r0, #0
2540    bne     .LOP_IGET_BOOLEAN_finish
2541    b       common_exceptionThrown
2542
2543
2544/* ------------------------------ */
2545    .balign 64
2546.L_OP_IGET_BYTE: /* 0x56 */
2547/* File: armv5te/OP_IGET_BYTE.S */
2548@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2549/* File: armv5te/OP_IGET.S */
2550    /*
2551     * General 32-bit instance field get.
2552     *
2553     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2554     */
2555    /* op vA, vB, field@CCCC */
2556    mov     r0, rINST, lsr #12          @ r0<- B
2557    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2558    FETCH(r1, 1)                        @ r1<- field ref CCCC
2559    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2560    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2561    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2562    cmp     r0, #0                      @ is resolved entry null?
2563    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25648:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2565    EXPORT_PC()                         @ resolve() could throw
2566    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2567    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2568    cmp     r0, #0
2569    bne     .LOP_IGET_BYTE_finish
2570    b       common_exceptionThrown
2571
2572
2573/* ------------------------------ */
2574    .balign 64
2575.L_OP_IGET_CHAR: /* 0x57 */
2576/* File: armv5te/OP_IGET_CHAR.S */
2577@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2578/* File: armv5te/OP_IGET.S */
2579    /*
2580     * General 32-bit instance field get.
2581     *
2582     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2583     */
2584    /* op vA, vB, field@CCCC */
2585    mov     r0, rINST, lsr #12          @ r0<- B
2586    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2587    FETCH(r1, 1)                        @ r1<- field ref CCCC
2588    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2589    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2590    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2591    cmp     r0, #0                      @ is resolved entry null?
2592    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25938:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2594    EXPORT_PC()                         @ resolve() could throw
2595    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2596    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2597    cmp     r0, #0
2598    bne     .LOP_IGET_CHAR_finish
2599    b       common_exceptionThrown
2600
2601
2602/* ------------------------------ */
2603    .balign 64
2604.L_OP_IGET_SHORT: /* 0x58 */
2605/* File: armv5te/OP_IGET_SHORT.S */
2606@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2607/* File: armv5te/OP_IGET.S */
2608    /*
2609     * General 32-bit instance field get.
2610     *
2611     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2612     */
2613    /* op vA, vB, field@CCCC */
2614    mov     r0, rINST, lsr #12          @ r0<- B
2615    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2616    FETCH(r1, 1)                        @ r1<- field ref CCCC
2617    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2618    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2619    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2620    cmp     r0, #0                      @ is resolved entry null?
2621    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26228:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2623    EXPORT_PC()                         @ resolve() could throw
2624    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2625    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2626    cmp     r0, #0
2627    bne     .LOP_IGET_SHORT_finish
2628    b       common_exceptionThrown
2629
2630
2631/* ------------------------------ */
2632    .balign 64
2633.L_OP_IPUT: /* 0x59 */
2634/* File: armv6t2/OP_IPUT.S */
2635    /*
2636     * General 32-bit instance field put.
2637     *
2638     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2639     */
2640    /* op vA, vB, field@CCCC */
2641    mov     r0, rINST, lsr #12          @ r0<- B
2642    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2643    FETCH(r1, 1)                        @ r1<- field ref CCCC
2644    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2645    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2646    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2647    cmp     r0, #0                      @ is resolved entry null?
2648    bne     .LOP_IPUT_finish          @ no, already resolved
26498:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2650    EXPORT_PC()                         @ resolve() could throw
2651    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2652    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2653    cmp     r0, #0                      @ success?
2654    bne     .LOP_IPUT_finish          @ yes, finish up
2655    b       common_exceptionThrown
2656
2657/* ------------------------------ */
2658    .balign 64
2659.L_OP_IPUT_WIDE: /* 0x5a */
2660/* File: armv6t2/OP_IPUT_WIDE.S */
2661    /* iput-wide vA, vB, field@CCCC */
2662    mov     r0, rINST, lsr #12          @ r0<- B
2663    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2664    FETCH(r1, 1)                        @ r1<- field ref CCCC
2665    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2666    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2667    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2668    cmp     r0, #0                      @ is resolved entry null?
2669    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26708:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2671    EXPORT_PC()                         @ resolve() could throw
2672    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2673    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2674    cmp     r0, #0                      @ success?
2675    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2676    b       common_exceptionThrown
2677
2678/* ------------------------------ */
2679    .balign 64
2680.L_OP_IPUT_OBJECT: /* 0x5b */
2681/* File: armv5te/OP_IPUT_OBJECT.S */
2682/* File: armv5te/OP_IPUT.S */
2683    /*
2684     * General 32-bit instance field put.
2685     *
2686     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2687     */
2688    /* op vA, vB, field@CCCC */
2689    mov     r0, rINST, lsr #12          @ r0<- B
2690    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2691    FETCH(r1, 1)                        @ r1<- field ref CCCC
2692    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2693    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2694    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2695    cmp     r0, #0                      @ is resolved entry null?
2696    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26978:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2698    EXPORT_PC()                         @ resolve() could throw
2699    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2700    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2701    cmp     r0, #0                      @ success?
2702    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2703    b       common_exceptionThrown
2704
2705
2706/* ------------------------------ */
2707    .balign 64
2708.L_OP_IPUT_BOOLEAN: /* 0x5c */
2709/* File: armv5te/OP_IPUT_BOOLEAN.S */
2710@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2711/* File: armv5te/OP_IPUT.S */
2712    /*
2713     * General 32-bit instance field put.
2714     *
2715     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2716     */
2717    /* op vA, vB, field@CCCC */
2718    mov     r0, rINST, lsr #12          @ r0<- B
2719    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2720    FETCH(r1, 1)                        @ r1<- field ref CCCC
2721    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2722    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2723    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2724    cmp     r0, #0                      @ is resolved entry null?
2725    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27268:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2727    EXPORT_PC()                         @ resolve() could throw
2728    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2729    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2730    cmp     r0, #0                      @ success?
2731    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2732    b       common_exceptionThrown
2733
2734
2735/* ------------------------------ */
2736    .balign 64
2737.L_OP_IPUT_BYTE: /* 0x5d */
2738/* File: armv5te/OP_IPUT_BYTE.S */
2739@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2740/* File: armv5te/OP_IPUT.S */
2741    /*
2742     * General 32-bit instance field put.
2743     *
2744     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2745     */
2746    /* op vA, vB, field@CCCC */
2747    mov     r0, rINST, lsr #12          @ r0<- B
2748    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2749    FETCH(r1, 1)                        @ r1<- field ref CCCC
2750    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2751    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2752    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2753    cmp     r0, #0                      @ is resolved entry null?
2754    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27558:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2756    EXPORT_PC()                         @ resolve() could throw
2757    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2758    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2759    cmp     r0, #0                      @ success?
2760    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2761    b       common_exceptionThrown
2762
2763
2764/* ------------------------------ */
2765    .balign 64
2766.L_OP_IPUT_CHAR: /* 0x5e */
2767/* File: armv5te/OP_IPUT_CHAR.S */
2768@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2769/* File: armv5te/OP_IPUT.S */
2770    /*
2771     * General 32-bit instance field put.
2772     *
2773     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2774     */
2775    /* op vA, vB, field@CCCC */
2776    mov     r0, rINST, lsr #12          @ r0<- B
2777    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2778    FETCH(r1, 1)                        @ r1<- field ref CCCC
2779    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2780    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2781    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2782    cmp     r0, #0                      @ is resolved entry null?
2783    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27848:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2785    EXPORT_PC()                         @ resolve() could throw
2786    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2787    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2788    cmp     r0, #0                      @ success?
2789    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2790    b       common_exceptionThrown
2791
2792
2793/* ------------------------------ */
2794    .balign 64
2795.L_OP_IPUT_SHORT: /* 0x5f */
2796/* File: armv5te/OP_IPUT_SHORT.S */
2797@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2798/* File: armv5te/OP_IPUT.S */
2799    /*
2800     * General 32-bit instance field put.
2801     *
2802     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2803     */
2804    /* op vA, vB, field@CCCC */
2805    mov     r0, rINST, lsr #12          @ r0<- B
2806    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2807    FETCH(r1, 1)                        @ r1<- field ref CCCC
2808    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2809    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2810    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2811    cmp     r0, #0                      @ is resolved entry null?
2812    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2814    EXPORT_PC()                         @ resolve() could throw
2815    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2816    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2817    cmp     r0, #0                      @ success?
2818    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2819    b       common_exceptionThrown
2820
2821
2822/* ------------------------------ */
2823    .balign 64
2824.L_OP_SGET: /* 0x60 */
2825/* File: armv5te/OP_SGET.S */
2826    /*
2827     * General 32-bit SGET handler.
2828     *
2829     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2830     */
2831    /* op vAA, field@BBBB */
2832    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2833    FETCH(r1, 1)                        @ r1<- field ref BBBB
2834    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2835    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2836    cmp     r0, #0                      @ is resolved entry null?
2837    beq     .LOP_SGET_resolve         @ yes, do resolve
2838.LOP_SGET_finish: @ field ptr in r0
2839    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2840    mov     r2, rINST, lsr #8           @ r2<- AA
2841    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2842    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2844    GOTO_OPCODE(ip)                     @ jump to next instruction
2845
2846/* ------------------------------ */
2847    .balign 64
2848.L_OP_SGET_WIDE: /* 0x61 */
2849/* File: armv5te/OP_SGET_WIDE.S */
2850    /*
2851     * 64-bit SGET handler.
2852     */
2853    /* sget-wide vAA, field@BBBB */
2854    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2855    FETCH(r1, 1)                        @ r1<- field ref BBBB
2856    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858    cmp     r0, #0                      @ is resolved entry null?
2859    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2860.LOP_SGET_WIDE_finish:
2861    mov     r1, rINST, lsr #8           @ r1<- AA
2862    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
2863    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
2864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
2866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867    GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869/* ------------------------------ */
2870    .balign 64
2871.L_OP_SGET_OBJECT: /* 0x62 */
2872/* File: armv5te/OP_SGET_OBJECT.S */
2873/* File: armv5te/OP_SGET.S */
2874    /*
2875     * General 32-bit SGET handler.
2876     *
2877     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2878     */
2879    /* op vAA, field@BBBB */
2880    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2881    FETCH(r1, 1)                        @ r1<- field ref BBBB
2882    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2883    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2884    cmp     r0, #0                      @ is resolved entry null?
2885    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2886.LOP_SGET_OBJECT_finish: @ field ptr in r0
2887    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2888    mov     r2, rINST, lsr #8           @ r2<- AA
2889    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2890    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2891    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2892    GOTO_OPCODE(ip)                     @ jump to next instruction
2893
2894
2895/* ------------------------------ */
2896    .balign 64
2897.L_OP_SGET_BOOLEAN: /* 0x63 */
2898/* File: armv5te/OP_SGET_BOOLEAN.S */
2899/* File: armv5te/OP_SGET.S */
2900    /*
2901     * General 32-bit SGET handler.
2902     *
2903     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2904     */
2905    /* op vAA, field@BBBB */
2906    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2907    FETCH(r1, 1)                        @ r1<- field ref BBBB
2908    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2909    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2910    cmp     r0, #0                      @ is resolved entry null?
2911    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2912.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2913    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2914    mov     r2, rINST, lsr #8           @ r2<- AA
2915    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2916    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2918    GOTO_OPCODE(ip)                     @ jump to next instruction
2919
2920
2921/* ------------------------------ */
2922    .balign 64
2923.L_OP_SGET_BYTE: /* 0x64 */
2924/* File: armv5te/OP_SGET_BYTE.S */
2925/* File: armv5te/OP_SGET.S */
2926    /*
2927     * General 32-bit SGET handler.
2928     *
2929     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2930     */
2931    /* op vAA, field@BBBB */
2932    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2933    FETCH(r1, 1)                        @ r1<- field ref BBBB
2934    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2935    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2936    cmp     r0, #0                      @ is resolved entry null?
2937    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2938.LOP_SGET_BYTE_finish: @ field ptr in r0
2939    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2940    mov     r2, rINST, lsr #8           @ r2<- AA
2941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2942    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2943    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2944    GOTO_OPCODE(ip)                     @ jump to next instruction
2945
2946
2947/* ------------------------------ */
2948    .balign 64
2949.L_OP_SGET_CHAR: /* 0x65 */
2950/* File: armv5te/OP_SGET_CHAR.S */
2951/* File: armv5te/OP_SGET.S */
2952    /*
2953     * General 32-bit SGET handler.
2954     *
2955     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2956     */
2957    /* op vAA, field@BBBB */
2958    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2959    FETCH(r1, 1)                        @ r1<- field ref BBBB
2960    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2961    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2962    cmp     r0, #0                      @ is resolved entry null?
2963    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2964.LOP_SGET_CHAR_finish: @ field ptr in r0
2965    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2966    mov     r2, rINST, lsr #8           @ r2<- AA
2967    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2968    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2969    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2970    GOTO_OPCODE(ip)                     @ jump to next instruction
2971
2972
2973/* ------------------------------ */
2974    .balign 64
2975.L_OP_SGET_SHORT: /* 0x66 */
2976/* File: armv5te/OP_SGET_SHORT.S */
2977/* File: armv5te/OP_SGET.S */
2978    /*
2979     * General 32-bit SGET handler.
2980     *
2981     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2982     */
2983    /* op vAA, field@BBBB */
2984    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2985    FETCH(r1, 1)                        @ r1<- field ref BBBB
2986    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2987    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2988    cmp     r0, #0                      @ is resolved entry null?
2989    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2990.LOP_SGET_SHORT_finish: @ field ptr in r0
2991    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2992    mov     r2, rINST, lsr #8           @ r2<- AA
2993    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2994    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2995    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2996    GOTO_OPCODE(ip)                     @ jump to next instruction
2997
2998
2999/* ------------------------------ */
3000    .balign 64
3001.L_OP_SPUT: /* 0x67 */
3002/* File: armv5te/OP_SPUT.S */
3003    /*
3004     * General 32-bit SPUT handler.
3005     *
3006     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3007     */
3008    /* op vAA, field@BBBB */
3009    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3010    FETCH(r1, 1)                        @ r1<- field ref BBBB
3011    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3012    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3013    cmp     r0, #0                      @ is resolved entry null?
3014    beq     .LOP_SPUT_resolve         @ yes, do resolve
3015.LOP_SPUT_finish:   @ field ptr in r0
3016    mov     r2, rINST, lsr #8           @ r2<- AA
3017    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3018    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3019    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3020    str     r1, [r0, #offStaticField_value] @ field<- vAA
3021    GOTO_OPCODE(ip)                     @ jump to next instruction
3022
3023/* ------------------------------ */
3024    .balign 64
3025.L_OP_SPUT_WIDE: /* 0x68 */
3026/* File: armv5te/OP_SPUT_WIDE.S */
3027    /*
3028     * 64-bit SPUT handler.
3029     */
3030    /* sput-wide vAA, field@BBBB */
3031    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3032    FETCH(r1, 1)                        @ r1<- field ref BBBB
3033    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3034    mov     r9, rINST, lsr #8           @ r9<- AA
3035    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3036    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3037    cmp     r0, #0                      @ is resolved entry null?
3038    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3039.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
3040    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3041    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
3042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3043    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
3044    GOTO_OPCODE(ip)                     @ jump to next instruction
3045
3046/* ------------------------------ */
3047    .balign 64
3048.L_OP_SPUT_OBJECT: /* 0x69 */
3049/* File: armv5te/OP_SPUT_OBJECT.S */
3050/* File: armv5te/OP_SPUT.S */
3051    /*
3052     * General 32-bit SPUT handler.
3053     *
3054     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3055     */
3056    /* op vAA, field@BBBB */
3057    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3058    FETCH(r1, 1)                        @ r1<- field ref BBBB
3059    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3060    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3061    cmp     r0, #0                      @ is resolved entry null?
3062    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3063.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3064    mov     r2, rINST, lsr #8           @ r2<- AA
3065    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3066    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3067    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3068    str     r1, [r0, #offStaticField_value] @ field<- vAA
3069    GOTO_OPCODE(ip)                     @ jump to next instruction
3070
3071
3072/* ------------------------------ */
3073    .balign 64
3074.L_OP_SPUT_BOOLEAN: /* 0x6a */
3075/* File: armv5te/OP_SPUT_BOOLEAN.S */
3076/* File: armv5te/OP_SPUT.S */
3077    /*
3078     * General 32-bit SPUT handler.
3079     *
3080     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3081     */
3082    /* op vAA, field@BBBB */
3083    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3084    FETCH(r1, 1)                        @ r1<- field ref BBBB
3085    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3086    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3087    cmp     r0, #0                      @ is resolved entry null?
3088    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3089.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3090    mov     r2, rINST, lsr #8           @ r2<- AA
3091    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3092    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3093    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3094    str     r1, [r0, #offStaticField_value] @ field<- vAA
3095    GOTO_OPCODE(ip)                     @ jump to next instruction
3096
3097
3098/* ------------------------------ */
3099    .balign 64
3100.L_OP_SPUT_BYTE: /* 0x6b */
3101/* File: armv5te/OP_SPUT_BYTE.S */
3102/* File: armv5te/OP_SPUT.S */
3103    /*
3104     * General 32-bit SPUT handler.
3105     *
3106     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3107     */
3108    /* op vAA, field@BBBB */
3109    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3110    FETCH(r1, 1)                        @ r1<- field ref BBBB
3111    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3112    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3113    cmp     r0, #0                      @ is resolved entry null?
3114    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3115.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3116    mov     r2, rINST, lsr #8           @ r2<- AA
3117    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3118    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3119    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3120    str     r1, [r0, #offStaticField_value] @ field<- vAA
3121    GOTO_OPCODE(ip)                     @ jump to next instruction
3122
3123
3124/* ------------------------------ */
3125    .balign 64
3126.L_OP_SPUT_CHAR: /* 0x6c */
3127/* File: armv5te/OP_SPUT_CHAR.S */
3128/* File: armv5te/OP_SPUT.S */
3129    /*
3130     * General 32-bit SPUT handler.
3131     *
3132     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3133     */
3134    /* op vAA, field@BBBB */
3135    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3136    FETCH(r1, 1)                        @ r1<- field ref BBBB
3137    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3138    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3139    cmp     r0, #0                      @ is resolved entry null?
3140    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3141.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3142    mov     r2, rINST, lsr #8           @ r2<- AA
3143    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3144    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3146    str     r1, [r0, #offStaticField_value] @ field<- vAA
3147    GOTO_OPCODE(ip)                     @ jump to next instruction
3148
3149
3150/* ------------------------------ */
3151    .balign 64
3152.L_OP_SPUT_SHORT: /* 0x6d */
3153/* File: armv5te/OP_SPUT_SHORT.S */
3154/* File: armv5te/OP_SPUT.S */
3155    /*
3156     * General 32-bit SPUT handler.
3157     *
3158     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3159     */
3160    /* op vAA, field@BBBB */
3161    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3162    FETCH(r1, 1)                        @ r1<- field ref BBBB
3163    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3164    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3165    cmp     r0, #0                      @ is resolved entry null?
3166    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3167.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3168    mov     r2, rINST, lsr #8           @ r2<- AA
3169    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3170    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3172    str     r1, [r0, #offStaticField_value] @ field<- vAA
3173    GOTO_OPCODE(ip)                     @ jump to next instruction
3174
3175
3176/* ------------------------------ */
3177    .balign 64
3178.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3179/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3180    /*
3181     * Handle a virtual method call.
3182     *
3183     * for: invoke-virtual, invoke-virtual/range
3184     */
3185    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3186    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3187    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3188    FETCH(r1, 1)                        @ r1<- BBBB
3189    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3190    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3191    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3192    .if     (!0)
3193    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3194    .endif
3195    cmp     r0, #0                      @ already resolved?
3196    EXPORT_PC()                         @ must export for invoke
3197    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3198    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3199    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3200    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3201    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3202    cmp     r0, #0                      @ got null?
3203    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3204    b       common_exceptionThrown      @ yes, handle exception
3205
3206/* ------------------------------ */
3207    .balign 64
3208.L_OP_INVOKE_SUPER: /* 0x6f */
3209/* File: armv5te/OP_INVOKE_SUPER.S */
3210    /*
3211     * Handle a "super" method call.
3212     *
3213     * for: invoke-super, invoke-super/range
3214     */
3215    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3216    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3217    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3218    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3219    .if     (!0)
3220    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3221    .endif
3222    FETCH(r1, 1)                        @ r1<- BBBB
3223    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3224    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3225    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3226    cmp     r2, #0                      @ null "this"?
3227    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3228    beq     common_errNullObject        @ null "this", throw exception
3229    cmp     r0, #0                      @ already resolved?
3230    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3231    EXPORT_PC()                         @ must export for invoke
3232    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3233    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3234
3235/* ------------------------------ */
3236    .balign 64
3237.L_OP_INVOKE_DIRECT: /* 0x70 */
3238/* File: armv5te/OP_INVOKE_DIRECT.S */
3239    /*
3240     * Handle a direct method call.
3241     *
3242     * (We could defer the "is 'this' pointer null" test to the common
3243     * method invocation code, and use a flag to indicate that static
3244     * calls don't count.  If we do this as part of copying the arguments
3245     * out we could avoiding loading the first arg twice.)
3246     *
3247     * for: invoke-direct, invoke-direct/range
3248     */
3249    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3250    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3251    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3252    FETCH(r1, 1)                        @ r1<- BBBB
3253    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3254    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3255    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3256    .if     (!0)
3257    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3258    .endif
3259    cmp     r0, #0                      @ already resolved?
3260    EXPORT_PC()                         @ must export for invoke
3261    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3262    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3263.LOP_INVOKE_DIRECT_finish:
3264    cmp     r2, #0                      @ null "this" ref?
3265    bne     common_invokeMethodNoRange   @ no, continue on
3266    b       common_errNullObject        @ yes, throw exception
3267
3268/* ------------------------------ */
3269    .balign 64
3270.L_OP_INVOKE_STATIC: /* 0x71 */
3271/* File: armv5te/OP_INVOKE_STATIC.S */
3272    /*
3273     * Handle a static method call.
3274     *
3275     * for: invoke-static, invoke-static/range
3276     */
3277    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3278    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3279    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3280    FETCH(r1, 1)                        @ r1<- BBBB
3281    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3282    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3283    cmp     r0, #0                      @ already resolved?
3284    EXPORT_PC()                         @ must export for invoke
3285    bne     common_invokeMethodNoRange @ yes, continue on
32860:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3287    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3288    mov     r2, #METHOD_STATIC          @ resolver method type
3289    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3290    cmp     r0, #0                      @ got null?
3291    bne     common_invokeMethodNoRange @ no, continue
3292    b       common_exceptionThrown      @ yes, handle exception
3293
3294
3295/* ------------------------------ */
3296    .balign 64
3297.L_OP_INVOKE_INTERFACE: /* 0x72 */
3298/* File: armv5te/OP_INVOKE_INTERFACE.S */
3299    /*
3300     * Handle an interface method call.
3301     *
3302     * for: invoke-interface, invoke-interface/range
3303     */
3304    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3305    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3306    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3307    FETCH(r1, 1)                        @ r1<- BBBB
3308    .if     (!0)
3309    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3310    .endif
3311    EXPORT_PC()                         @ must export for invoke
3312    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3313    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3314    cmp     r0, #0                      @ null obj?
3315    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3316    beq     common_errNullObject        @ yes, fail
3317    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3318    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3319    cmp     r0, #0                      @ failed?
3320    beq     common_exceptionThrown      @ yes, handle exception
3321    b       common_invokeMethodNoRange @ jump to common handler
3322
3323
3324/* ------------------------------ */
3325    .balign 64
3326.L_OP_UNUSED_73: /* 0x73 */
3327/* File: armv5te/OP_UNUSED_73.S */
3328/* File: armv5te/unused.S */
3329    bl      common_abort
3330
3331
3332
3333/* ------------------------------ */
3334    .balign 64
3335.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3336/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3337/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3338    /*
3339     * Handle a virtual method call.
3340     *
3341     * for: invoke-virtual, invoke-virtual/range
3342     */
3343    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3344    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3345    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3346    FETCH(r1, 1)                        @ r1<- BBBB
3347    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3348    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3349    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3350    .if     (!1)
3351    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3352    .endif
3353    cmp     r0, #0                      @ already resolved?
3354    EXPORT_PC()                         @ must export for invoke
3355    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3356    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3357    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3358    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3359    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3360    cmp     r0, #0                      @ got null?
3361    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3362    b       common_exceptionThrown      @ yes, handle exception
3363
3364
3365/* ------------------------------ */
3366    .balign 64
3367.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3368/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3369/* File: armv5te/OP_INVOKE_SUPER.S */
3370    /*
3371     * Handle a "super" method call.
3372     *
3373     * for: invoke-super, invoke-super/range
3374     */
3375    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3376    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3377    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3378    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3379    .if     (!1)
3380    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3381    .endif
3382    FETCH(r1, 1)                        @ r1<- BBBB
3383    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3384    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3385    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3386    cmp     r2, #0                      @ null "this"?
3387    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3388    beq     common_errNullObject        @ null "this", throw exception
3389    cmp     r0, #0                      @ already resolved?
3390    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3391    EXPORT_PC()                         @ must export for invoke
3392    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3393    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3394
3395
3396/* ------------------------------ */
3397    .balign 64
3398.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3399/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3400/* File: armv5te/OP_INVOKE_DIRECT.S */
3401    /*
3402     * Handle a direct method call.
3403     *
3404     * (We could defer the "is 'this' pointer null" test to the common
3405     * method invocation code, and use a flag to indicate that static
3406     * calls don't count.  If we do this as part of copying the arguments
3407     * out we could avoiding loading the first arg twice.)
3408     *
3409     * for: invoke-direct, invoke-direct/range
3410     */
3411    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3412    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3413    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3414    FETCH(r1, 1)                        @ r1<- BBBB
3415    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3416    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3417    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3418    .if     (!1)
3419    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3420    .endif
3421    cmp     r0, #0                      @ already resolved?
3422    EXPORT_PC()                         @ must export for invoke
3423    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3424    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3425.LOP_INVOKE_DIRECT_RANGE_finish:
3426    cmp     r2, #0                      @ null "this" ref?
3427    bne     common_invokeMethodRange   @ no, continue on
3428    b       common_errNullObject        @ yes, throw exception
3429
3430
3431/* ------------------------------ */
3432    .balign 64
3433.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3434/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3435/* File: armv5te/OP_INVOKE_STATIC.S */
3436    /*
3437     * Handle a static method call.
3438     *
3439     * for: invoke-static, invoke-static/range
3440     */
3441    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3442    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3443    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3444    FETCH(r1, 1)                        @ r1<- BBBB
3445    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3446    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3447    cmp     r0, #0                      @ already resolved?
3448    EXPORT_PC()                         @ must export for invoke
3449    bne     common_invokeMethodRange @ yes, continue on
34500:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3451    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3452    mov     r2, #METHOD_STATIC          @ resolver method type
3453    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3454    cmp     r0, #0                      @ got null?
3455    bne     common_invokeMethodRange @ no, continue
3456    b       common_exceptionThrown      @ yes, handle exception
3457
3458
3459
3460/* ------------------------------ */
3461    .balign 64
3462.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3463/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3464/* File: armv5te/OP_INVOKE_INTERFACE.S */
3465    /*
3466     * Handle an interface method call.
3467     *
3468     * for: invoke-interface, invoke-interface/range
3469     */
3470    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3471    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3472    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3473    FETCH(r1, 1)                        @ r1<- BBBB
3474    .if     (!1)
3475    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3476    .endif
3477    EXPORT_PC()                         @ must export for invoke
3478    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3479    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3480    cmp     r0, #0                      @ null obj?
3481    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3482    beq     common_errNullObject        @ yes, fail
3483    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3484    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3485    cmp     r0, #0                      @ failed?
3486    beq     common_exceptionThrown      @ yes, handle exception
3487    b       common_invokeMethodRange @ jump to common handler
3488
3489
3490
3491/* ------------------------------ */
3492    .balign 64
3493.L_OP_UNUSED_79: /* 0x79 */
3494/* File: armv5te/OP_UNUSED_79.S */
3495/* File: armv5te/unused.S */
3496    bl      common_abort
3497
3498
3499
3500/* ------------------------------ */
3501    .balign 64
3502.L_OP_UNUSED_7A: /* 0x7a */
3503/* File: armv5te/OP_UNUSED_7A.S */
3504/* File: armv5te/unused.S */
3505    bl      common_abort
3506
3507
3508
3509/* ------------------------------ */
3510    .balign 64
3511.L_OP_NEG_INT: /* 0x7b */
3512/* File: armv6t2/OP_NEG_INT.S */
3513/* File: armv6t2/unop.S */
3514    /*
3515     * Generic 32-bit unary operation.  Provide an "instr" line that
3516     * specifies an instruction that performs "result = op r0".
3517     * This could be an ARM instruction or a function call.
3518     *
3519     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3520     *      int-to-byte, int-to-char, int-to-short
3521     */
3522    /* unop vA, vB */
3523    mov     r3, rINST, lsr #12          @ r3<- B
3524    ubfx    r9, rINST, #8, #4           @ r9<- A
3525    GET_VREG(r0, r3)                    @ r0<- vB
3526                               @ optional op; may set condition codes
3527    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3528    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3529    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3530    SET_VREG(r0, r9)                    @ vAA<- r0
3531    GOTO_OPCODE(ip)                     @ jump to next instruction
3532    /* 8-9 instructions */
3533
3534
3535/* ------------------------------ */
3536    .balign 64
3537.L_OP_NOT_INT: /* 0x7c */
3538/* File: armv6t2/OP_NOT_INT.S */
3539/* File: armv6t2/unop.S */
3540    /*
3541     * Generic 32-bit unary operation.  Provide an "instr" line that
3542     * specifies an instruction that performs "result = op r0".
3543     * This could be an ARM instruction or a function call.
3544     *
3545     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3546     *      int-to-byte, int-to-char, int-to-short
3547     */
3548    /* unop vA, vB */
3549    mov     r3, rINST, lsr #12          @ r3<- B
3550    ubfx    r9, rINST, #8, #4           @ r9<- A
3551    GET_VREG(r0, r3)                    @ r0<- vB
3552                               @ optional op; may set condition codes
3553    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3554    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3555    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3556    SET_VREG(r0, r9)                    @ vAA<- r0
3557    GOTO_OPCODE(ip)                     @ jump to next instruction
3558    /* 8-9 instructions */
3559
3560
3561/* ------------------------------ */
3562    .balign 64
3563.L_OP_NEG_LONG: /* 0x7d */
3564/* File: armv6t2/OP_NEG_LONG.S */
3565/* File: armv6t2/unopWide.S */
3566    /*
3567     * Generic 64-bit unary operation.  Provide an "instr" line that
3568     * specifies an instruction that performs "result = op r0/r1".
3569     * This could be an ARM instruction or a function call.
3570     *
3571     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3572     */
3573    /* unop vA, vB */
3574    mov     r3, rINST, lsr #12          @ r3<- B
3575    ubfx    r9, rINST, #8, #4           @ r9<- A
3576    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3577    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3578    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3579    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3580    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3581    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3582    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3583    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3584    GOTO_OPCODE(ip)                     @ jump to next instruction
3585    /* 10-11 instructions */
3586
3587
3588
3589/* ------------------------------ */
3590    .balign 64
3591.L_OP_NOT_LONG: /* 0x7e */
3592/* File: armv6t2/OP_NOT_LONG.S */
3593/* File: armv6t2/unopWide.S */
3594    /*
3595     * Generic 64-bit unary operation.  Provide an "instr" line that
3596     * specifies an instruction that performs "result = op r0/r1".
3597     * This could be an ARM instruction or a function call.
3598     *
3599     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3600     */
3601    /* unop vA, vB */
3602    mov     r3, rINST, lsr #12          @ r3<- B
3603    ubfx    r9, rINST, #8, #4           @ r9<- A
3604    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3605    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3606    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3607    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3608    mvn     r0, r0                           @ optional op; may set condition codes
3609    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3610    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3611    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3612    GOTO_OPCODE(ip)                     @ jump to next instruction
3613    /* 10-11 instructions */
3614
3615
3616
3617/* ------------------------------ */
3618    .balign 64
3619.L_OP_NEG_FLOAT: /* 0x7f */
3620/* File: armv6t2/OP_NEG_FLOAT.S */
3621/* File: armv6t2/unop.S */
3622    /*
3623     * Generic 32-bit unary operation.  Provide an "instr" line that
3624     * specifies an instruction that performs "result = op r0".
3625     * This could be an ARM instruction or a function call.
3626     *
3627     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3628     *      int-to-byte, int-to-char, int-to-short
3629     */
3630    /* unop vA, vB */
3631    mov     r3, rINST, lsr #12          @ r3<- B
3632    ubfx    r9, rINST, #8, #4           @ r9<- A
3633    GET_VREG(r0, r3)                    @ r0<- vB
3634                               @ optional op; may set condition codes
3635    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3636    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3638    SET_VREG(r0, r9)                    @ vAA<- r0
3639    GOTO_OPCODE(ip)                     @ jump to next instruction
3640    /* 8-9 instructions */
3641
3642
3643/* ------------------------------ */
3644    .balign 64
3645.L_OP_NEG_DOUBLE: /* 0x80 */
3646/* File: armv6t2/OP_NEG_DOUBLE.S */
3647/* File: armv6t2/unopWide.S */
3648    /*
3649     * Generic 64-bit unary operation.  Provide an "instr" line that
3650     * specifies an instruction that performs "result = op r0/r1".
3651     * This could be an ARM instruction or a function call.
3652     *
3653     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3654     */
3655    /* unop vA, vB */
3656    mov     r3, rINST, lsr #12          @ r3<- B
3657    ubfx    r9, rINST, #8, #4           @ r9<- A
3658    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3659    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3660    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3661    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3662                               @ optional op; may set condition codes
3663    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3664    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3665    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3666    GOTO_OPCODE(ip)                     @ jump to next instruction
3667    /* 10-11 instructions */
3668
3669
3670
3671/* ------------------------------ */
3672    .balign 64
3673.L_OP_INT_TO_LONG: /* 0x81 */
3674/* File: armv6t2/OP_INT_TO_LONG.S */
3675/* File: armv6t2/unopWider.S */
3676    /*
3677     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3678     * that specifies an instruction that performs "result = op r0", where
3679     * "result" is a 64-bit quantity in r0/r1.
3680     *
3681     * For: int-to-long, int-to-double, float-to-long, float-to-double
3682     */
3683    /* unop vA, vB */
3684    mov     r3, rINST, lsr #12          @ r3<- B
3685    ubfx    r9, rINST, #8, #4           @ r9<- A
3686    GET_VREG(r0, r3)                    @ r0<- vB
3687    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3688                               @ optional op; may set condition codes
3689    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3690    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3691    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3692    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3693    GOTO_OPCODE(ip)                     @ jump to next instruction
3694    /* 9-10 instructions */
3695
3696
3697/* ------------------------------ */
3698    .balign 64
3699.L_OP_INT_TO_FLOAT: /* 0x82 */
3700/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3701/* File: arm-vfp/funop.S */
3702    /*
3703     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3704     * line that specifies an instruction that performs "s1 = op s0".
3705     *
3706     * for: int-to-float, float-to-int
3707     */
3708    /* unop vA, vB */
3709    mov     r3, rINST, lsr #12          @ r3<- B
3710    mov     r9, rINST, lsr #8           @ r9<- A+
3711    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3712    flds    s0, [r3]                    @ s0<- vB
3713    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3714    and     r9, r9, #15                 @ r9<- A
3715    fsitos  s1, s0                              @ s1<- op
3716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3717    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3718    fsts    s1, [r9]                    @ vA<- s1
3719    GOTO_OPCODE(ip)                     @ jump to next instruction
3720
3721
3722/* ------------------------------ */
3723    .balign 64
3724.L_OP_INT_TO_DOUBLE: /* 0x83 */
3725/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3726/* File: arm-vfp/funopWider.S */
3727    /*
3728     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3729     * "instr" line that specifies an instruction that performs "d0 = op s0".
3730     *
3731     * For: int-to-double, float-to-double
3732     */
3733    /* unop vA, vB */
3734    mov     r3, rINST, lsr #12          @ r3<- B
3735    mov     r9, rINST, lsr #8           @ r9<- A+
3736    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3737    flds    s0, [r3]                    @ s0<- vB
3738    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3739    and     r9, r9, #15                 @ r9<- A
3740    fsitod  d0, s0                              @ d0<- op
3741    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3742    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3743    fstd    d0, [r9]                    @ vA<- d0
3744    GOTO_OPCODE(ip)                     @ jump to next instruction
3745
3746
3747/* ------------------------------ */
3748    .balign 64
3749.L_OP_LONG_TO_INT: /* 0x84 */
3750/* File: armv5te/OP_LONG_TO_INT.S */
3751/* we ignore the high word, making this equivalent to a 32-bit reg move */
3752/* File: armv5te/OP_MOVE.S */
3753    /* for move, move-object, long-to-int */
3754    /* op vA, vB */
3755    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3756    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3757    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3758    GET_VREG(r2, r1)                    @ r2<- fp[B]
3759    and     r0, r0, #15
3760    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3761    SET_VREG(r2, r0)                    @ fp[A]<- r2
3762    GOTO_OPCODE(ip)                     @ execute next instruction
3763
3764
3765
3766/* ------------------------------ */
3767    .balign 64
3768.L_OP_LONG_TO_FLOAT: /* 0x85 */
3769/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3770/* File: armv6t2/unopNarrower.S */
3771    /*
3772     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3773     * that specifies an instruction that performs "result = op r0/r1", where
3774     * "result" is a 32-bit quantity in r0.
3775     *
3776     * For: long-to-float, double-to-int, double-to-float
3777     *
3778     * (This would work for long-to-int, but that instruction is actually
3779     * an exact match for OP_MOVE.)
3780     */
3781    /* unop vA, vB */
3782    mov     r3, rINST, lsr #12          @ r3<- B
3783    ubfx    r9, rINST, #8, #4           @ r9<- A
3784    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3785    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3786    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3787                               @ optional op; may set condition codes
3788    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3790    SET_VREG(r0, r9)                    @ vA<- r0
3791    GOTO_OPCODE(ip)                     @ jump to next instruction
3792    /* 9-10 instructions */
3793
3794
3795/* ------------------------------ */
3796    .balign 64
3797.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3798/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3799/* File: armv6t2/unopWide.S */
3800    /*
3801     * Generic 64-bit unary operation.  Provide an "instr" line that
3802     * specifies an instruction that performs "result = op r0/r1".
3803     * This could be an ARM instruction or a function call.
3804     *
3805     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3806     */
3807    /* unop vA, vB */
3808    mov     r3, rINST, lsr #12          @ r3<- B
3809    ubfx    r9, rINST, #8, #4           @ r9<- A
3810    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3811    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3812    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3813    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3814                               @ optional op; may set condition codes
3815    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3817    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3818    GOTO_OPCODE(ip)                     @ jump to next instruction
3819    /* 10-11 instructions */
3820
3821
3822
3823/* ------------------------------ */
3824    .balign 64
3825.L_OP_FLOAT_TO_INT: /* 0x87 */
3826/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3827/* File: arm-vfp/funop.S */
3828    /*
3829     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3830     * line that specifies an instruction that performs "s1 = op s0".
3831     *
3832     * for: int-to-float, float-to-int
3833     */
3834    /* unop vA, vB */
3835    mov     r3, rINST, lsr #12          @ r3<- B
3836    mov     r9, rINST, lsr #8           @ r9<- A+
3837    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3838    flds    s0, [r3]                    @ s0<- vB
3839    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3840    and     r9, r9, #15                 @ r9<- A
3841    ftosizs s1, s0                              @ s1<- op
3842    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3843    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3844    fsts    s1, [r9]                    @ vA<- s1
3845    GOTO_OPCODE(ip)                     @ jump to next instruction
3846
3847
3848/* ------------------------------ */
3849    .balign 64
3850.L_OP_FLOAT_TO_LONG: /* 0x88 */
3851/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3852@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3853/* File: armv6t2/unopWider.S */
3854    /*
3855     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3856     * that specifies an instruction that performs "result = op r0", where
3857     * "result" is a 64-bit quantity in r0/r1.
3858     *
3859     * For: int-to-long, int-to-double, float-to-long, float-to-double
3860     */
3861    /* unop vA, vB */
3862    mov     r3, rINST, lsr #12          @ r3<- B
3863    ubfx    r9, rINST, #8, #4           @ r9<- A
3864    GET_VREG(r0, r3)                    @ r0<- vB
3865    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3866                               @ optional op; may set condition codes
3867    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3868    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3870    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3871    GOTO_OPCODE(ip)                     @ jump to next instruction
3872    /* 9-10 instructions */
3873
3874
3875
3876/* ------------------------------ */
3877    .balign 64
3878.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3879/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3880/* File: arm-vfp/funopWider.S */
3881    /*
3882     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3883     * "instr" line that specifies an instruction that performs "d0 = op s0".
3884     *
3885     * For: int-to-double, float-to-double
3886     */
3887    /* unop vA, vB */
3888    mov     r3, rINST, lsr #12          @ r3<- B
3889    mov     r9, rINST, lsr #8           @ r9<- A+
3890    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3891    flds    s0, [r3]                    @ s0<- vB
3892    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3893    and     r9, r9, #15                 @ r9<- A
3894    fcvtds  d0, s0                              @ d0<- op
3895    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3896    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3897    fstd    d0, [r9]                    @ vA<- d0
3898    GOTO_OPCODE(ip)                     @ jump to next instruction
3899
3900
3901/* ------------------------------ */
3902    .balign 64
3903.L_OP_DOUBLE_TO_INT: /* 0x8a */
3904/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3905/* File: arm-vfp/funopNarrower.S */
3906    /*
3907     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3908     * "instr" line that specifies an instruction that performs "s0 = op d0".
3909     *
3910     * For: double-to-int, double-to-float
3911     */
3912    /* unop vA, vB */
3913    mov     r3, rINST, lsr #12          @ r3<- B
3914    mov     r9, rINST, lsr #8           @ r9<- A+
3915    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3916    fldd    d0, [r3]                    @ d0<- vB
3917    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3918    and     r9, r9, #15                 @ r9<- A
3919    ftosizd  s0, d0                              @ s0<- op
3920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3921    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3922    fsts    s0, [r9]                    @ vA<- s0
3923    GOTO_OPCODE(ip)                     @ jump to next instruction
3924
3925
3926/* ------------------------------ */
3927    .balign 64
3928.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3929/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3930@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3931/* File: armv6t2/unopWide.S */
3932    /*
3933     * Generic 64-bit unary operation.  Provide an "instr" line that
3934     * specifies an instruction that performs "result = op r0/r1".
3935     * This could be an ARM instruction or a function call.
3936     *
3937     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3938     */
3939    /* unop vA, vB */
3940    mov     r3, rINST, lsr #12          @ r3<- B
3941    ubfx    r9, rINST, #8, #4           @ r9<- A
3942    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3943    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3944    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3945    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3946                               @ optional op; may set condition codes
3947    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3948    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3949    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3950    GOTO_OPCODE(ip)                     @ jump to next instruction
3951    /* 10-11 instructions */
3952
3953
3954
3955
3956/* ------------------------------ */
3957    .balign 64
3958.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3959/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3960/* File: arm-vfp/funopNarrower.S */
3961    /*
3962     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3963     * "instr" line that specifies an instruction that performs "s0 = op d0".
3964     *
3965     * For: double-to-int, double-to-float
3966     */
3967    /* unop vA, vB */
3968    mov     r3, rINST, lsr #12          @ r3<- B
3969    mov     r9, rINST, lsr #8           @ r9<- A+
3970    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3971    fldd    d0, [r3]                    @ d0<- vB
3972    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3973    and     r9, r9, #15                 @ r9<- A
3974    fcvtsd  s0, d0                              @ s0<- op
3975    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3976    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3977    fsts    s0, [r9]                    @ vA<- s0
3978    GOTO_OPCODE(ip)                     @ jump to next instruction
3979
3980
3981/* ------------------------------ */
3982    .balign 64
3983.L_OP_INT_TO_BYTE: /* 0x8d */
3984/* File: armv6t2/OP_INT_TO_BYTE.S */
3985/* File: armv6t2/unop.S */
3986    /*
3987     * Generic 32-bit unary operation.  Provide an "instr" line that
3988     * specifies an instruction that performs "result = op r0".
3989     * This could be an ARM instruction or a function call.
3990     *
3991     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3992     *      int-to-byte, int-to-char, int-to-short
3993     */
3994    /* unop vA, vB */
3995    mov     r3, rINST, lsr #12          @ r3<- B
3996    ubfx    r9, rINST, #8, #4           @ r9<- A
3997    GET_VREG(r0, r3)                    @ r0<- vB
3998                               @ optional op; may set condition codes
3999    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4000    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
4001    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4002    SET_VREG(r0, r9)                    @ vAA<- r0
4003    GOTO_OPCODE(ip)                     @ jump to next instruction
4004    /* 8-9 instructions */
4005
4006
4007/* ------------------------------ */
4008    .balign 64
4009.L_OP_INT_TO_CHAR: /* 0x8e */
4010/* File: armv6t2/OP_INT_TO_CHAR.S */
4011/* File: armv6t2/unop.S */
4012    /*
4013     * Generic 32-bit unary operation.  Provide an "instr" line that
4014     * specifies an instruction that performs "result = op r0".
4015     * This could be an ARM instruction or a function call.
4016     *
4017     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4018     *      int-to-byte, int-to-char, int-to-short
4019     */
4020    /* unop vA, vB */
4021    mov     r3, rINST, lsr #12          @ r3<- B
4022    ubfx    r9, rINST, #8, #4           @ r9<- A
4023    GET_VREG(r0, r3)                    @ r0<- vB
4024                               @ optional op; may set condition codes
4025    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4026    uxth    r0, r0                              @ r0<- op, r0-r3 changed
4027    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4028    SET_VREG(r0, r9)                    @ vAA<- r0
4029    GOTO_OPCODE(ip)                     @ jump to next instruction
4030    /* 8-9 instructions */
4031
4032
4033/* ------------------------------ */
4034    .balign 64
4035.L_OP_INT_TO_SHORT: /* 0x8f */
4036/* File: armv6t2/OP_INT_TO_SHORT.S */
4037/* File: armv6t2/unop.S */
4038    /*
4039     * Generic 32-bit unary operation.  Provide an "instr" line that
4040     * specifies an instruction that performs "result = op r0".
4041     * This could be an ARM instruction or a function call.
4042     *
4043     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4044     *      int-to-byte, int-to-char, int-to-short
4045     */
4046    /* unop vA, vB */
4047    mov     r3, rINST, lsr #12          @ r3<- B
4048    ubfx    r9, rINST, #8, #4           @ r9<- A
4049    GET_VREG(r0, r3)                    @ r0<- vB
4050                               @ optional op; may set condition codes
4051    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4052    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4053    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4054    SET_VREG(r0, r9)                    @ vAA<- r0
4055    GOTO_OPCODE(ip)                     @ jump to next instruction
4056    /* 8-9 instructions */
4057
4058
4059/* ------------------------------ */
4060    .balign 64
4061.L_OP_ADD_INT: /* 0x90 */
4062/* File: armv5te/OP_ADD_INT.S */
4063/* File: armv5te/binop.S */
4064    /*
4065     * Generic 32-bit binary operation.  Provide an "instr" line that
4066     * specifies an instruction that performs "result = r0 op r1".
4067     * This could be an ARM instruction or a function call.  (If the result
4068     * comes back in a register other than r0, you can override "result".)
4069     *
4070     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4071     * vCC (r1).  Useful for integer division and modulus.  Note that we
4072     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4073     * handles it correctly.
4074     *
4075     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4076     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4077     *      mul-float, div-float, rem-float
4078     */
4079    /* binop vAA, vBB, vCC */
4080    FETCH(r0, 1)                        @ r0<- CCBB
4081    mov     r9, rINST, lsr #8           @ r9<- AA
4082    mov     r3, r0, lsr #8              @ r3<- CC
4083    and     r2, r0, #255                @ r2<- BB
4084    GET_VREG(r1, r3)                    @ r1<- vCC
4085    GET_VREG(r0, r2)                    @ r0<- vBB
4086    .if 0
4087    cmp     r1, #0                      @ is second operand zero?
4088    beq     common_errDivideByZero
4089    .endif
4090
4091    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4092                               @ optional op; may set condition codes
4093    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4094    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4095    SET_VREG(r0, r9)               @ vAA<- r0
4096    GOTO_OPCODE(ip)                     @ jump to next instruction
4097    /* 11-14 instructions */
4098
4099
4100
4101/* ------------------------------ */
4102    .balign 64
4103.L_OP_SUB_INT: /* 0x91 */
4104/* File: armv5te/OP_SUB_INT.S */
4105/* File: armv5te/binop.S */
4106    /*
4107     * Generic 32-bit binary operation.  Provide an "instr" line that
4108     * specifies an instruction that performs "result = r0 op r1".
4109     * This could be an ARM instruction or a function call.  (If the result
4110     * comes back in a register other than r0, you can override "result".)
4111     *
4112     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4113     * vCC (r1).  Useful for integer division and modulus.  Note that we
4114     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4115     * handles it correctly.
4116     *
4117     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4118     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4119     *      mul-float, div-float, rem-float
4120     */
4121    /* binop vAA, vBB, vCC */
4122    FETCH(r0, 1)                        @ r0<- CCBB
4123    mov     r9, rINST, lsr #8           @ r9<- AA
4124    mov     r3, r0, lsr #8              @ r3<- CC
4125    and     r2, r0, #255                @ r2<- BB
4126    GET_VREG(r1, r3)                    @ r1<- vCC
4127    GET_VREG(r0, r2)                    @ r0<- vBB
4128    .if 0
4129    cmp     r1, #0                      @ is second operand zero?
4130    beq     common_errDivideByZero
4131    .endif
4132
4133    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4134                               @ optional op; may set condition codes
4135    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4136    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4137    SET_VREG(r0, r9)               @ vAA<- r0
4138    GOTO_OPCODE(ip)                     @ jump to next instruction
4139    /* 11-14 instructions */
4140
4141
4142
4143/* ------------------------------ */
4144    .balign 64
4145.L_OP_MUL_INT: /* 0x92 */
4146/* File: armv5te/OP_MUL_INT.S */
4147/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4148/* File: armv5te/binop.S */
4149    /*
4150     * Generic 32-bit binary operation.  Provide an "instr" line that
4151     * specifies an instruction that performs "result = r0 op r1".
4152     * This could be an ARM instruction or a function call.  (If the result
4153     * comes back in a register other than r0, you can override "result".)
4154     *
4155     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4156     * vCC (r1).  Useful for integer division and modulus.  Note that we
4157     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4158     * handles it correctly.
4159     *
4160     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4161     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4162     *      mul-float, div-float, rem-float
4163     */
4164    /* binop vAA, vBB, vCC */
4165    FETCH(r0, 1)                        @ r0<- CCBB
4166    mov     r9, rINST, lsr #8           @ r9<- AA
4167    mov     r3, r0, lsr #8              @ r3<- CC
4168    and     r2, r0, #255                @ r2<- BB
4169    GET_VREG(r1, r3)                    @ r1<- vCC
4170    GET_VREG(r0, r2)                    @ r0<- vBB
4171    .if 0
4172    cmp     r1, #0                      @ is second operand zero?
4173    beq     common_errDivideByZero
4174    .endif
4175
4176    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4177                               @ optional op; may set condition codes
4178    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4180    SET_VREG(r0, r9)               @ vAA<- r0
4181    GOTO_OPCODE(ip)                     @ jump to next instruction
4182    /* 11-14 instructions */
4183
4184
4185
4186/* ------------------------------ */
4187    .balign 64
4188.L_OP_DIV_INT: /* 0x93 */
4189/* File: armv5te/OP_DIV_INT.S */
4190/* File: armv5te/binop.S */
4191    /*
4192     * Generic 32-bit binary operation.  Provide an "instr" line that
4193     * specifies an instruction that performs "result = r0 op r1".
4194     * This could be an ARM instruction or a function call.  (If the result
4195     * comes back in a register other than r0, you can override "result".)
4196     *
4197     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4198     * vCC (r1).  Useful for integer division and modulus.  Note that we
4199     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4200     * handles it correctly.
4201     *
4202     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4203     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4204     *      mul-float, div-float, rem-float
4205     */
4206    /* binop vAA, vBB, vCC */
4207    FETCH(r0, 1)                        @ r0<- CCBB
4208    mov     r9, rINST, lsr #8           @ r9<- AA
4209    mov     r3, r0, lsr #8              @ r3<- CC
4210    and     r2, r0, #255                @ r2<- BB
4211    GET_VREG(r1, r3)                    @ r1<- vCC
4212    GET_VREG(r0, r2)                    @ r0<- vBB
4213    .if 1
4214    cmp     r1, #0                      @ is second operand zero?
4215    beq     common_errDivideByZero
4216    .endif
4217
4218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4219                               @ optional op; may set condition codes
4220    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4221    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4222    SET_VREG(r0, r9)               @ vAA<- r0
4223    GOTO_OPCODE(ip)                     @ jump to next instruction
4224    /* 11-14 instructions */
4225
4226
4227
4228/* ------------------------------ */
4229    .balign 64
4230.L_OP_REM_INT: /* 0x94 */
4231/* File: armv5te/OP_REM_INT.S */
4232/* idivmod returns quotient in r0 and remainder in r1 */
4233/* File: armv5te/binop.S */
4234    /*
4235     * Generic 32-bit binary operation.  Provide an "instr" line that
4236     * specifies an instruction that performs "result = r0 op r1".
4237     * This could be an ARM instruction or a function call.  (If the result
4238     * comes back in a register other than r0, you can override "result".)
4239     *
4240     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4241     * vCC (r1).  Useful for integer division and modulus.  Note that we
4242     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4243     * handles it correctly.
4244     *
4245     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4246     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4247     *      mul-float, div-float, rem-float
4248     */
4249    /* binop vAA, vBB, vCC */
4250    FETCH(r0, 1)                        @ r0<- CCBB
4251    mov     r9, rINST, lsr #8           @ r9<- AA
4252    mov     r3, r0, lsr #8              @ r3<- CC
4253    and     r2, r0, #255                @ r2<- BB
4254    GET_VREG(r1, r3)                    @ r1<- vCC
4255    GET_VREG(r0, r2)                    @ r0<- vBB
4256    .if 1
4257    cmp     r1, #0                      @ is second operand zero?
4258    beq     common_errDivideByZero
4259    .endif
4260
4261    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4262                               @ optional op; may set condition codes
4263    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4264    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4265    SET_VREG(r1, r9)               @ vAA<- r1
4266    GOTO_OPCODE(ip)                     @ jump to next instruction
4267    /* 11-14 instructions */
4268
4269
4270
4271/* ------------------------------ */
4272    .balign 64
4273.L_OP_AND_INT: /* 0x95 */
4274/* File: armv5te/OP_AND_INT.S */
4275/* File: armv5te/binop.S */
4276    /*
4277     * Generic 32-bit binary operation.  Provide an "instr" line that
4278     * specifies an instruction that performs "result = r0 op r1".
4279     * This could be an ARM instruction or a function call.  (If the result
4280     * comes back in a register other than r0, you can override "result".)
4281     *
4282     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4283     * vCC (r1).  Useful for integer division and modulus.  Note that we
4284     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4285     * handles it correctly.
4286     *
4287     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4288     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4289     *      mul-float, div-float, rem-float
4290     */
4291    /* binop vAA, vBB, vCC */
4292    FETCH(r0, 1)                        @ r0<- CCBB
4293    mov     r9, rINST, lsr #8           @ r9<- AA
4294    mov     r3, r0, lsr #8              @ r3<- CC
4295    and     r2, r0, #255                @ r2<- BB
4296    GET_VREG(r1, r3)                    @ r1<- vCC
4297    GET_VREG(r0, r2)                    @ r0<- vBB
4298    .if 0
4299    cmp     r1, #0                      @ is second operand zero?
4300    beq     common_errDivideByZero
4301    .endif
4302
4303    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4304                               @ optional op; may set condition codes
4305    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4306    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4307    SET_VREG(r0, r9)               @ vAA<- r0
4308    GOTO_OPCODE(ip)                     @ jump to next instruction
4309    /* 11-14 instructions */
4310
4311
4312
4313/* ------------------------------ */
4314    .balign 64
4315.L_OP_OR_INT: /* 0x96 */
4316/* File: armv5te/OP_OR_INT.S */
4317/* File: armv5te/binop.S */
4318    /*
4319     * Generic 32-bit binary operation.  Provide an "instr" line that
4320     * specifies an instruction that performs "result = r0 op r1".
4321     * This could be an ARM instruction or a function call.  (If the result
4322     * comes back in a register other than r0, you can override "result".)
4323     *
4324     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4325     * vCC (r1).  Useful for integer division and modulus.  Note that we
4326     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4327     * handles it correctly.
4328     *
4329     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4330     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4331     *      mul-float, div-float, rem-float
4332     */
4333    /* binop vAA, vBB, vCC */
4334    FETCH(r0, 1)                        @ r0<- CCBB
4335    mov     r9, rINST, lsr #8           @ r9<- AA
4336    mov     r3, r0, lsr #8              @ r3<- CC
4337    and     r2, r0, #255                @ r2<- BB
4338    GET_VREG(r1, r3)                    @ r1<- vCC
4339    GET_VREG(r0, r2)                    @ r0<- vBB
4340    .if 0
4341    cmp     r1, #0                      @ is second operand zero?
4342    beq     common_errDivideByZero
4343    .endif
4344
4345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4346                               @ optional op; may set condition codes
4347    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4349    SET_VREG(r0, r9)               @ vAA<- r0
4350    GOTO_OPCODE(ip)                     @ jump to next instruction
4351    /* 11-14 instructions */
4352
4353
4354
4355/* ------------------------------ */
4356    .balign 64
4357.L_OP_XOR_INT: /* 0x97 */
4358/* File: armv5te/OP_XOR_INT.S */
4359/* File: armv5te/binop.S */
4360    /*
4361     * Generic 32-bit binary operation.  Provide an "instr" line that
4362     * specifies an instruction that performs "result = r0 op r1".
4363     * This could be an ARM instruction or a function call.  (If the result
4364     * comes back in a register other than r0, you can override "result".)
4365     *
4366     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4367     * vCC (r1).  Useful for integer division and modulus.  Note that we
4368     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4369     * handles it correctly.
4370     *
4371     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4372     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4373     *      mul-float, div-float, rem-float
4374     */
4375    /* binop vAA, vBB, vCC */
4376    FETCH(r0, 1)                        @ r0<- CCBB
4377    mov     r9, rINST, lsr #8           @ r9<- AA
4378    mov     r3, r0, lsr #8              @ r3<- CC
4379    and     r2, r0, #255                @ r2<- BB
4380    GET_VREG(r1, r3)                    @ r1<- vCC
4381    GET_VREG(r0, r2)                    @ r0<- vBB
4382    .if 0
4383    cmp     r1, #0                      @ is second operand zero?
4384    beq     common_errDivideByZero
4385    .endif
4386
4387    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4388                               @ optional op; may set condition codes
4389    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4391    SET_VREG(r0, r9)               @ vAA<- r0
4392    GOTO_OPCODE(ip)                     @ jump to next instruction
4393    /* 11-14 instructions */
4394
4395
4396
4397/* ------------------------------ */
4398    .balign 64
4399.L_OP_SHL_INT: /* 0x98 */
4400/* File: armv5te/OP_SHL_INT.S */
4401/* File: armv5te/binop.S */
4402    /*
4403     * Generic 32-bit binary operation.  Provide an "instr" line that
4404     * specifies an instruction that performs "result = r0 op r1".
4405     * This could be an ARM instruction or a function call.  (If the result
4406     * comes back in a register other than r0, you can override "result".)
4407     *
4408     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4409     * vCC (r1).  Useful for integer division and modulus.  Note that we
4410     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4411     * handles it correctly.
4412     *
4413     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4414     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4415     *      mul-float, div-float, rem-float
4416     */
4417    /* binop vAA, vBB, vCC */
4418    FETCH(r0, 1)                        @ r0<- CCBB
4419    mov     r9, rINST, lsr #8           @ r9<- AA
4420    mov     r3, r0, lsr #8              @ r3<- CC
4421    and     r2, r0, #255                @ r2<- BB
4422    GET_VREG(r1, r3)                    @ r1<- vCC
4423    GET_VREG(r0, r2)                    @ r0<- vBB
4424    .if 0
4425    cmp     r1, #0                      @ is second operand zero?
4426    beq     common_errDivideByZero
4427    .endif
4428
4429    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4430    and     r1, r1, #31                           @ optional op; may set condition codes
4431    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4432    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4433    SET_VREG(r0, r9)               @ vAA<- r0
4434    GOTO_OPCODE(ip)                     @ jump to next instruction
4435    /* 11-14 instructions */
4436
4437
4438
4439/* ------------------------------ */
4440    .balign 64
4441.L_OP_SHR_INT: /* 0x99 */
4442/* File: armv5te/OP_SHR_INT.S */
4443/* File: armv5te/binop.S */
4444    /*
4445     * Generic 32-bit binary operation.  Provide an "instr" line that
4446     * specifies an instruction that performs "result = r0 op r1".
4447     * This could be an ARM instruction or a function call.  (If the result
4448     * comes back in a register other than r0, you can override "result".)
4449     *
4450     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4451     * vCC (r1).  Useful for integer division and modulus.  Note that we
4452     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4453     * handles it correctly.
4454     *
4455     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4456     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4457     *      mul-float, div-float, rem-float
4458     */
4459    /* binop vAA, vBB, vCC */
4460    FETCH(r0, 1)                        @ r0<- CCBB
4461    mov     r9, rINST, lsr #8           @ r9<- AA
4462    mov     r3, r0, lsr #8              @ r3<- CC
4463    and     r2, r0, #255                @ r2<- BB
4464    GET_VREG(r1, r3)                    @ r1<- vCC
4465    GET_VREG(r0, r2)                    @ r0<- vBB
4466    .if 0
4467    cmp     r1, #0                      @ is second operand zero?
4468    beq     common_errDivideByZero
4469    .endif
4470
4471    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4472    and     r1, r1, #31                           @ optional op; may set condition codes
4473    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4475    SET_VREG(r0, r9)               @ vAA<- r0
4476    GOTO_OPCODE(ip)                     @ jump to next instruction
4477    /* 11-14 instructions */
4478
4479
4480
4481/* ------------------------------ */
4482    .balign 64
4483.L_OP_USHR_INT: /* 0x9a */
4484/* File: armv5te/OP_USHR_INT.S */
4485/* File: armv5te/binop.S */
4486    /*
4487     * Generic 32-bit binary operation.  Provide an "instr" line that
4488     * specifies an instruction that performs "result = r0 op r1".
4489     * This could be an ARM instruction or a function call.  (If the result
4490     * comes back in a register other than r0, you can override "result".)
4491     *
4492     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4493     * vCC (r1).  Useful for integer division and modulus.  Note that we
4494     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4495     * handles it correctly.
4496     *
4497     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4498     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4499     *      mul-float, div-float, rem-float
4500     */
4501    /* binop vAA, vBB, vCC */
4502    FETCH(r0, 1)                        @ r0<- CCBB
4503    mov     r9, rINST, lsr #8           @ r9<- AA
4504    mov     r3, r0, lsr #8              @ r3<- CC
4505    and     r2, r0, #255                @ r2<- BB
4506    GET_VREG(r1, r3)                    @ r1<- vCC
4507    GET_VREG(r0, r2)                    @ r0<- vBB
4508    .if 0
4509    cmp     r1, #0                      @ is second operand zero?
4510    beq     common_errDivideByZero
4511    .endif
4512
4513    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4514    and     r1, r1, #31                           @ optional op; may set condition codes
4515    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4517    SET_VREG(r0, r9)               @ vAA<- r0
4518    GOTO_OPCODE(ip)                     @ jump to next instruction
4519    /* 11-14 instructions */
4520
4521
4522
4523/* ------------------------------ */
4524    .balign 64
4525.L_OP_ADD_LONG: /* 0x9b */
4526/* File: armv5te/OP_ADD_LONG.S */
4527/* File: armv5te/binopWide.S */
4528    /*
4529     * Generic 64-bit binary operation.  Provide an "instr" line that
4530     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4531     * This could be an ARM instruction or a function call.  (If the result
4532     * comes back in a register other than r0, you can override "result".)
4533     *
4534     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4535     * vCC (r1).  Useful for integer division and modulus.
4536     *
4537     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4538     *      xor-long, add-double, sub-double, mul-double, div-double,
4539     *      rem-double
4540     *
4541     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4542     */
4543    /* binop vAA, vBB, vCC */
4544    FETCH(r0, 1)                        @ r0<- CCBB
4545    mov     r9, rINST, lsr #8           @ r9<- AA
4546    and     r2, r0, #255                @ r2<- BB
4547    mov     r3, r0, lsr #8              @ r3<- CC
4548    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4549    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4550    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4551    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4552    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4553    .if 0
4554    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4555    beq     common_errDivideByZero
4556    .endif
4557    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4558
4559    adds    r0, r0, r2                           @ optional op; may set condition codes
4560    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4561    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4562    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4563    GOTO_OPCODE(ip)                     @ jump to next instruction
4564    /* 14-17 instructions */
4565
4566
4567
4568/* ------------------------------ */
4569    .balign 64
4570.L_OP_SUB_LONG: /* 0x9c */
4571/* File: armv5te/OP_SUB_LONG.S */
4572/* File: armv5te/binopWide.S */
4573    /*
4574     * Generic 64-bit binary operation.  Provide an "instr" line that
4575     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4576     * This could be an ARM instruction or a function call.  (If the result
4577     * comes back in a register other than r0, you can override "result".)
4578     *
4579     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4580     * vCC (r1).  Useful for integer division and modulus.
4581     *
4582     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4583     *      xor-long, add-double, sub-double, mul-double, div-double,
4584     *      rem-double
4585     *
4586     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4587     */
4588    /* binop vAA, vBB, vCC */
4589    FETCH(r0, 1)                        @ r0<- CCBB
4590    mov     r9, rINST, lsr #8           @ r9<- AA
4591    and     r2, r0, #255                @ r2<- BB
4592    mov     r3, r0, lsr #8              @ r3<- CC
4593    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4594    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4595    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4596    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4597    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4598    .if 0
4599    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4600    beq     common_errDivideByZero
4601    .endif
4602    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4603
4604    subs    r0, r0, r2                           @ optional op; may set condition codes
4605    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4606    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4607    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4608    GOTO_OPCODE(ip)                     @ jump to next instruction
4609    /* 14-17 instructions */
4610
4611
4612
4613/* ------------------------------ */
4614    .balign 64
4615.L_OP_MUL_LONG: /* 0x9d */
4616/* File: armv5te/OP_MUL_LONG.S */
4617    /*
4618     * Signed 64-bit integer multiply.
4619     *
4620     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4621     *        WX
4622     *      x YZ
4623     *  --------
4624     *     ZW ZX
4625     *  YW YX
4626     *
4627     * The low word of the result holds ZX, the high word holds
4628     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4629     * it doesn't fit in the low 64 bits.
4630     *
4631     * Unlike most ARM math operations, multiply instructions have
4632     * restrictions on using the same register more than once (Rd and Rm
4633     * cannot be the same).
4634     */
4635    /* mul-long vAA, vBB, vCC */
4636    FETCH(r0, 1)                        @ r0<- CCBB
4637    and     r2, r0, #255                @ r2<- BB
4638    mov     r3, r0, lsr #8              @ r3<- CC
4639    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4640    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4641    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4642    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4643    mul     ip, r2, r1                  @  ip<- ZxW
4644    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4645    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4646    mov     r0, rINST, lsr #8           @ r0<- AA
4647    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4648    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4649    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4650    b       .LOP_MUL_LONG_finish
4651
4652/* ------------------------------ */
4653    .balign 64
4654.L_OP_DIV_LONG: /* 0x9e */
4655/* File: armv5te/OP_DIV_LONG.S */
4656/* File: armv5te/binopWide.S */
4657    /*
4658     * Generic 64-bit binary operation.  Provide an "instr" line that
4659     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4660     * This could be an ARM instruction or a function call.  (If the result
4661     * comes back in a register other than r0, you can override "result".)
4662     *
4663     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4664     * vCC (r1).  Useful for integer division and modulus.
4665     *
4666     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4667     *      xor-long, add-double, sub-double, mul-double, div-double,
4668     *      rem-double
4669     *
4670     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4671     */
4672    /* binop vAA, vBB, vCC */
4673    FETCH(r0, 1)                        @ r0<- CCBB
4674    mov     r9, rINST, lsr #8           @ r9<- AA
4675    and     r2, r0, #255                @ r2<- BB
4676    mov     r3, r0, lsr #8              @ r3<- CC
4677    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4678    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4679    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4680    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4681    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4682    .if 1
4683    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4684    beq     common_errDivideByZero
4685    .endif
4686    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4687
4688                               @ optional op; may set condition codes
4689    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4690    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4691    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4692    GOTO_OPCODE(ip)                     @ jump to next instruction
4693    /* 14-17 instructions */
4694
4695
4696
4697/* ------------------------------ */
4698    .balign 64
4699.L_OP_REM_LONG: /* 0x9f */
4700/* File: armv5te/OP_REM_LONG.S */
4701/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4702/* File: armv5te/binopWide.S */
4703    /*
4704     * Generic 64-bit binary operation.  Provide an "instr" line that
4705     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4706     * This could be an ARM instruction or a function call.  (If the result
4707     * comes back in a register other than r0, you can override "result".)
4708     *
4709     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4710     * vCC (r1).  Useful for integer division and modulus.
4711     *
4712     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4713     *      xor-long, add-double, sub-double, mul-double, div-double,
4714     *      rem-double
4715     *
4716     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4717     */
4718    /* binop vAA, vBB, vCC */
4719    FETCH(r0, 1)                        @ r0<- CCBB
4720    mov     r9, rINST, lsr #8           @ r9<- AA
4721    and     r2, r0, #255                @ r2<- BB
4722    mov     r3, r0, lsr #8              @ r3<- CC
4723    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4724    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4725    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4726    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4727    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4728    .if 1
4729    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4730    beq     common_errDivideByZero
4731    .endif
4732    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4733
4734                               @ optional op; may set condition codes
4735    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4737    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4738    GOTO_OPCODE(ip)                     @ jump to next instruction
4739    /* 14-17 instructions */
4740
4741
4742
4743/* ------------------------------ */
4744    .balign 64
4745.L_OP_AND_LONG: /* 0xa0 */
4746/* File: armv5te/OP_AND_LONG.S */
4747/* File: armv5te/binopWide.S */
4748    /*
4749     * Generic 64-bit binary operation.  Provide an "instr" line that
4750     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4751     * This could be an ARM instruction or a function call.  (If the result
4752     * comes back in a register other than r0, you can override "result".)
4753     *
4754     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4755     * vCC (r1).  Useful for integer division and modulus.
4756     *
4757     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4758     *      xor-long, add-double, sub-double, mul-double, div-double,
4759     *      rem-double
4760     *
4761     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4762     */
4763    /* binop vAA, vBB, vCC */
4764    FETCH(r0, 1)                        @ r0<- CCBB
4765    mov     r9, rINST, lsr #8           @ r9<- AA
4766    and     r2, r0, #255                @ r2<- BB
4767    mov     r3, r0, lsr #8              @ r3<- CC
4768    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4769    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4770    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4771    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4772    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4773    .if 0
4774    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4775    beq     common_errDivideByZero
4776    .endif
4777    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4778
4779    and     r0, r0, r2                           @ optional op; may set condition codes
4780    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4781    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4782    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4783    GOTO_OPCODE(ip)                     @ jump to next instruction
4784    /* 14-17 instructions */
4785
4786
4787
4788/* ------------------------------ */
4789    .balign 64
4790.L_OP_OR_LONG: /* 0xa1 */
4791/* File: armv5te/OP_OR_LONG.S */
4792/* File: armv5te/binopWide.S */
4793    /*
4794     * Generic 64-bit binary operation.  Provide an "instr" line that
4795     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4796     * This could be an ARM instruction or a function call.  (If the result
4797     * comes back in a register other than r0, you can override "result".)
4798     *
4799     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4800     * vCC (r1).  Useful for integer division and modulus.
4801     *
4802     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4803     *      xor-long, add-double, sub-double, mul-double, div-double,
4804     *      rem-double
4805     *
4806     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4807     */
4808    /* binop vAA, vBB, vCC */
4809    FETCH(r0, 1)                        @ r0<- CCBB
4810    mov     r9, rINST, lsr #8           @ r9<- AA
4811    and     r2, r0, #255                @ r2<- BB
4812    mov     r3, r0, lsr #8              @ r3<- CC
4813    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4814    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4815    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4816    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4817    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4818    .if 0
4819    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4820    beq     common_errDivideByZero
4821    .endif
4822    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4823
4824    orr     r0, r0, r2                           @ optional op; may set condition codes
4825    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4827    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4828    GOTO_OPCODE(ip)                     @ jump to next instruction
4829    /* 14-17 instructions */
4830
4831
4832
4833/* ------------------------------ */
4834    .balign 64
4835.L_OP_XOR_LONG: /* 0xa2 */
4836/* File: armv5te/OP_XOR_LONG.S */
4837/* File: armv5te/binopWide.S */
4838    /*
4839     * Generic 64-bit binary operation.  Provide an "instr" line that
4840     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4841     * This could be an ARM instruction or a function call.  (If the result
4842     * comes back in a register other than r0, you can override "result".)
4843     *
4844     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4845     * vCC (r1).  Useful for integer division and modulus.
4846     *
4847     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4848     *      xor-long, add-double, sub-double, mul-double, div-double,
4849     *      rem-double
4850     *
4851     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4852     */
4853    /* binop vAA, vBB, vCC */
4854    FETCH(r0, 1)                        @ r0<- CCBB
4855    mov     r9, rINST, lsr #8           @ r9<- AA
4856    and     r2, r0, #255                @ r2<- BB
4857    mov     r3, r0, lsr #8              @ r3<- CC
4858    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4859    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4860    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4861    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4862    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4863    .if 0
4864    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4865    beq     common_errDivideByZero
4866    .endif
4867    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4868
4869    eor     r0, r0, r2                           @ optional op; may set condition codes
4870    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4871    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4872    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4873    GOTO_OPCODE(ip)                     @ jump to next instruction
4874    /* 14-17 instructions */
4875
4876
4877
4878/* ------------------------------ */
4879    .balign 64
4880.L_OP_SHL_LONG: /* 0xa3 */
4881/* File: armv5te/OP_SHL_LONG.S */
4882    /*
4883     * Long integer shift.  This is different from the generic 32/64-bit
4884     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4885     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4886     * 6 bits of the shift distance.
4887     */
4888    /* shl-long vAA, vBB, vCC */
4889    FETCH(r0, 1)                        @ r0<- CCBB
4890    mov     r9, rINST, lsr #8           @ r9<- AA
4891    and     r3, r0, #255                @ r3<- BB
4892    mov     r0, r0, lsr #8              @ r0<- CC
4893    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4894    GET_VREG(r2, r0)                    @ r2<- vCC
4895    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4896    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4897    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4898
4899    mov     r1, r1, asl r2              @  r1<- r1 << r2
4900    rsb     r3, r2, #32                 @  r3<- 32 - r2
4901    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4902    subs    ip, r2, #32                 @  ip<- r2 - 32
4903    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4904    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4905    b       .LOP_SHL_LONG_finish
4906
4907/* ------------------------------ */
4908    .balign 64
4909.L_OP_SHR_LONG: /* 0xa4 */
4910/* File: armv5te/OP_SHR_LONG.S */
4911    /*
4912     * Long integer shift.  This is different from the generic 32/64-bit
4913     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4914     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4915     * 6 bits of the shift distance.
4916     */
4917    /* shr-long vAA, vBB, vCC */
4918    FETCH(r0, 1)                        @ r0<- CCBB
4919    mov     r9, rINST, lsr #8           @ r9<- AA
4920    and     r3, r0, #255                @ r3<- BB
4921    mov     r0, r0, lsr #8              @ r0<- CC
4922    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4923    GET_VREG(r2, r0)                    @ r2<- vCC
4924    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4925    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4926    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4927
4928    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4929    rsb     r3, r2, #32                 @  r3<- 32 - r2
4930    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4931    subs    ip, r2, #32                 @  ip<- r2 - 32
4932    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4933    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4934    b       .LOP_SHR_LONG_finish
4935
4936/* ------------------------------ */
4937    .balign 64
4938.L_OP_USHR_LONG: /* 0xa5 */
4939/* File: armv5te/OP_USHR_LONG.S */
4940    /*
4941     * Long integer shift.  This is different from the generic 32/64-bit
4942     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4943     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4944     * 6 bits of the shift distance.
4945     */
4946    /* ushr-long vAA, vBB, vCC */
4947    FETCH(r0, 1)                        @ r0<- CCBB
4948    mov     r9, rINST, lsr #8           @ r9<- AA
4949    and     r3, r0, #255                @ r3<- BB
4950    mov     r0, r0, lsr #8              @ r0<- CC
4951    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4952    GET_VREG(r2, r0)                    @ r2<- vCC
4953    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4954    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4955    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4956
4957    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4958    rsb     r3, r2, #32                 @  r3<- 32 - r2
4959    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4960    subs    ip, r2, #32                 @  ip<- r2 - 32
4961    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4962    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4963    b       .LOP_USHR_LONG_finish
4964
4965/* ------------------------------ */
4966    .balign 64
4967.L_OP_ADD_FLOAT: /* 0xa6 */
4968/* File: arm-vfp/OP_ADD_FLOAT.S */
4969/* File: arm-vfp/fbinop.S */
4970    /*
4971     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4972     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4973     * use the "softfp" ABI, this must be an instruction, not a function call.
4974     *
4975     * For: add-float, sub-float, mul-float, div-float
4976     */
4977    /* floatop vAA, vBB, vCC */
4978    FETCH(r0, 1)                        @ r0<- CCBB
4979    mov     r9, rINST, lsr #8           @ r9<- AA
4980    mov     r3, r0, lsr #8              @ r3<- CC
4981    and     r2, r0, #255                @ r2<- BB
4982    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4983    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4984    flds    s1, [r3]                    @ s1<- vCC
4985    flds    s0, [r2]                    @ s0<- vBB
4986
4987    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4988    fadds   s2, s0, s1                              @ s2<- op
4989    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4990    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4991    fsts    s2, [r9]                    @ vAA<- s2
4992    GOTO_OPCODE(ip)                     @ jump to next instruction
4993
4994
4995/* ------------------------------ */
4996    .balign 64
4997.L_OP_SUB_FLOAT: /* 0xa7 */
4998/* File: arm-vfp/OP_SUB_FLOAT.S */
4999/* File: arm-vfp/fbinop.S */
5000    /*
5001     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5002     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5003     * use the "softfp" ABI, this must be an instruction, not a function call.
5004     *
5005     * For: add-float, sub-float, mul-float, div-float
5006     */
5007    /* floatop vAA, vBB, vCC */
5008    FETCH(r0, 1)                        @ r0<- CCBB
5009    mov     r9, rINST, lsr #8           @ r9<- AA
5010    mov     r3, r0, lsr #8              @ r3<- CC
5011    and     r2, r0, #255                @ r2<- BB
5012    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5013    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5014    flds    s1, [r3]                    @ s1<- vCC
5015    flds    s0, [r2]                    @ s0<- vBB
5016
5017    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5018    fsubs   s2, s0, s1                              @ s2<- op
5019    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5020    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5021    fsts    s2, [r9]                    @ vAA<- s2
5022    GOTO_OPCODE(ip)                     @ jump to next instruction
5023
5024
5025/* ------------------------------ */
5026    .balign 64
5027.L_OP_MUL_FLOAT: /* 0xa8 */
5028/* File: arm-vfp/OP_MUL_FLOAT.S */
5029/* File: arm-vfp/fbinop.S */
5030    /*
5031     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5032     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5033     * use the "softfp" ABI, this must be an instruction, not a function call.
5034     *
5035     * For: add-float, sub-float, mul-float, div-float
5036     */
5037    /* floatop vAA, vBB, vCC */
5038    FETCH(r0, 1)                        @ r0<- CCBB
5039    mov     r9, rINST, lsr #8           @ r9<- AA
5040    mov     r3, r0, lsr #8              @ r3<- CC
5041    and     r2, r0, #255                @ r2<- BB
5042    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5043    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5044    flds    s1, [r3]                    @ s1<- vCC
5045    flds    s0, [r2]                    @ s0<- vBB
5046
5047    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5048    fmuls   s2, s0, s1                              @ s2<- op
5049    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5050    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5051    fsts    s2, [r9]                    @ vAA<- s2
5052    GOTO_OPCODE(ip)                     @ jump to next instruction
5053
5054
5055/* ------------------------------ */
5056    .balign 64
5057.L_OP_DIV_FLOAT: /* 0xa9 */
5058/* File: arm-vfp/OP_DIV_FLOAT.S */
5059/* File: arm-vfp/fbinop.S */
5060    /*
5061     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5062     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5063     * use the "softfp" ABI, this must be an instruction, not a function call.
5064     *
5065     * For: add-float, sub-float, mul-float, div-float
5066     */
5067    /* floatop vAA, vBB, vCC */
5068    FETCH(r0, 1)                        @ r0<- CCBB
5069    mov     r9, rINST, lsr #8           @ r9<- AA
5070    mov     r3, r0, lsr #8              @ r3<- CC
5071    and     r2, r0, #255                @ r2<- BB
5072    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5073    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5074    flds    s1, [r3]                    @ s1<- vCC
5075    flds    s0, [r2]                    @ s0<- vBB
5076
5077    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5078    fdivs   s2, s0, s1                              @ s2<- op
5079    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5080    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5081    fsts    s2, [r9]                    @ vAA<- s2
5082    GOTO_OPCODE(ip)                     @ jump to next instruction
5083
5084
5085/* ------------------------------ */
5086    .balign 64
5087.L_OP_REM_FLOAT: /* 0xaa */
5088/* File: armv5te/OP_REM_FLOAT.S */
5089/* EABI doesn't define a float remainder function, but libm does */
5090/* File: armv5te/binop.S */
5091    /*
5092     * Generic 32-bit binary operation.  Provide an "instr" line that
5093     * specifies an instruction that performs "result = r0 op r1".
5094     * This could be an ARM instruction or a function call.  (If the result
5095     * comes back in a register other than r0, you can override "result".)
5096     *
5097     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5098     * vCC (r1).  Useful for integer division and modulus.  Note that we
5099     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5100     * handles it correctly.
5101     *
5102     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5103     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5104     *      mul-float, div-float, rem-float
5105     */
5106    /* binop vAA, vBB, vCC */
5107    FETCH(r0, 1)                        @ r0<- CCBB
5108    mov     r9, rINST, lsr #8           @ r9<- AA
5109    mov     r3, r0, lsr #8              @ r3<- CC
5110    and     r2, r0, #255                @ r2<- BB
5111    GET_VREG(r1, r3)                    @ r1<- vCC
5112    GET_VREG(r0, r2)                    @ r0<- vBB
5113    .if 0
5114    cmp     r1, #0                      @ is second operand zero?
5115    beq     common_errDivideByZero
5116    .endif
5117
5118    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5119                               @ optional op; may set condition codes
5120    bl      fmodf                              @ r0<- op, r0-r3 changed
5121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5122    SET_VREG(r0, r9)               @ vAA<- r0
5123    GOTO_OPCODE(ip)                     @ jump to next instruction
5124    /* 11-14 instructions */
5125
5126
5127
5128/* ------------------------------ */
5129    .balign 64
5130.L_OP_ADD_DOUBLE: /* 0xab */
5131/* File: arm-vfp/OP_ADD_DOUBLE.S */
5132/* File: arm-vfp/fbinopWide.S */
5133    /*
5134     * Generic 64-bit double-precision floating point binary operation.
5135     * Provide an "instr" line that specifies an instruction that performs
5136     * "d2 = d0 op d1".
5137     *
5138     * for: add-double, sub-double, mul-double, div-double
5139     */
5140    /* doubleop vAA, vBB, vCC */
5141    FETCH(r0, 1)                        @ r0<- CCBB
5142    mov     r9, rINST, lsr #8           @ r9<- AA
5143    mov     r3, r0, lsr #8              @ r3<- CC
5144    and     r2, r0, #255                @ r2<- BB
5145    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5146    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5147    fldd    d1, [r3]                    @ d1<- vCC
5148    fldd    d0, [r2]                    @ d0<- vBB
5149
5150    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5151    faddd   d2, d0, d1                              @ s2<- op
5152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5153    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5154    fstd    d2, [r9]                    @ vAA<- d2
5155    GOTO_OPCODE(ip)                     @ jump to next instruction
5156
5157
5158/* ------------------------------ */
5159    .balign 64
5160.L_OP_SUB_DOUBLE: /* 0xac */
5161/* File: arm-vfp/OP_SUB_DOUBLE.S */
5162/* File: arm-vfp/fbinopWide.S */
5163    /*
5164     * Generic 64-bit double-precision floating point binary operation.
5165     * Provide an "instr" line that specifies an instruction that performs
5166     * "d2 = d0 op d1".
5167     *
5168     * for: add-double, sub-double, mul-double, div-double
5169     */
5170    /* doubleop vAA, vBB, vCC */
5171    FETCH(r0, 1)                        @ r0<- CCBB
5172    mov     r9, rINST, lsr #8           @ r9<- AA
5173    mov     r3, r0, lsr #8              @ r3<- CC
5174    and     r2, r0, #255                @ r2<- BB
5175    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5176    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5177    fldd    d1, [r3]                    @ d1<- vCC
5178    fldd    d0, [r2]                    @ d0<- vBB
5179
5180    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5181    fsubd   d2, d0, d1                              @ s2<- op
5182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5183    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5184    fstd    d2, [r9]                    @ vAA<- d2
5185    GOTO_OPCODE(ip)                     @ jump to next instruction
5186
5187
5188/* ------------------------------ */
5189    .balign 64
5190.L_OP_MUL_DOUBLE: /* 0xad */
5191/* File: arm-vfp/OP_MUL_DOUBLE.S */
5192/* File: arm-vfp/fbinopWide.S */
5193    /*
5194     * Generic 64-bit double-precision floating point binary operation.
5195     * Provide an "instr" line that specifies an instruction that performs
5196     * "d2 = d0 op d1".
5197     *
5198     * for: add-double, sub-double, mul-double, div-double
5199     */
5200    /* doubleop vAA, vBB, vCC */
5201    FETCH(r0, 1)                        @ r0<- CCBB
5202    mov     r9, rINST, lsr #8           @ r9<- AA
5203    mov     r3, r0, lsr #8              @ r3<- CC
5204    and     r2, r0, #255                @ r2<- BB
5205    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5206    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5207    fldd    d1, [r3]                    @ d1<- vCC
5208    fldd    d0, [r2]                    @ d0<- vBB
5209
5210    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5211    fmuld   d2, d0, d1                              @ s2<- op
5212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5213    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5214    fstd    d2, [r9]                    @ vAA<- d2
5215    GOTO_OPCODE(ip)                     @ jump to next instruction
5216
5217
5218/* ------------------------------ */
5219    .balign 64
5220.L_OP_DIV_DOUBLE: /* 0xae */
5221/* File: arm-vfp/OP_DIV_DOUBLE.S */
5222/* File: arm-vfp/fbinopWide.S */
5223    /*
5224     * Generic 64-bit double-precision floating point binary operation.
5225     * Provide an "instr" line that specifies an instruction that performs
5226     * "d2 = d0 op d1".
5227     *
5228     * for: add-double, sub-double, mul-double, div-double
5229     */
5230    /* doubleop vAA, vBB, vCC */
5231    FETCH(r0, 1)                        @ r0<- CCBB
5232    mov     r9, rINST, lsr #8           @ r9<- AA
5233    mov     r3, r0, lsr #8              @ r3<- CC
5234    and     r2, r0, #255                @ r2<- BB
5235    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5236    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5237    fldd    d1, [r3]                    @ d1<- vCC
5238    fldd    d0, [r2]                    @ d0<- vBB
5239
5240    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5241    fdivd   d2, d0, d1                              @ s2<- op
5242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5243    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5244    fstd    d2, [r9]                    @ vAA<- d2
5245    GOTO_OPCODE(ip)                     @ jump to next instruction
5246
5247
5248/* ------------------------------ */
5249    .balign 64
5250.L_OP_REM_DOUBLE: /* 0xaf */
5251/* File: armv5te/OP_REM_DOUBLE.S */
5252/* EABI doesn't define a double remainder function, but libm does */
5253/* File: armv5te/binopWide.S */
5254    /*
5255     * Generic 64-bit binary operation.  Provide an "instr" line that
5256     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5257     * This could be an ARM instruction or a function call.  (If the result
5258     * comes back in a register other than r0, you can override "result".)
5259     *
5260     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5261     * vCC (r1).  Useful for integer division and modulus.
5262     *
5263     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5264     *      xor-long, add-double, sub-double, mul-double, div-double,
5265     *      rem-double
5266     *
5267     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5268     */
5269    /* binop vAA, vBB, vCC */
5270    FETCH(r0, 1)                        @ r0<- CCBB
5271    mov     r9, rINST, lsr #8           @ r9<- AA
5272    and     r2, r0, #255                @ r2<- BB
5273    mov     r3, r0, lsr #8              @ r3<- CC
5274    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5275    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5276    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5277    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5278    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5279    .if 0
5280    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5281    beq     common_errDivideByZero
5282    .endif
5283    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5284
5285                               @ optional op; may set condition codes
5286    bl      fmod                              @ result<- op, r0-r3 changed
5287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5288    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5289    GOTO_OPCODE(ip)                     @ jump to next instruction
5290    /* 14-17 instructions */
5291
5292
5293
5294/* ------------------------------ */
5295    .balign 64
5296.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5297/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5298/* File: armv6t2/binop2addr.S */
5299    /*
5300     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5301     * that specifies an instruction that performs "result = r0 op r1".
5302     * This could be an ARM instruction or a function call.  (If the result
5303     * comes back in a register other than r0, you can override "result".)
5304     *
5305     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5306     * vCC (r1).  Useful for integer division and modulus.
5307     *
5308     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5309     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5310     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5311     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5312     */
5313    /* binop/2addr vA, vB */
5314    mov     r3, rINST, lsr #12          @ r3<- B
5315    ubfx    r9, rINST, #8, #4           @ r9<- A
5316    GET_VREG(r1, r3)                    @ r1<- vB
5317    GET_VREG(r0, r9)                    @ r0<- vA
5318    .if 0
5319    cmp     r1, #0                      @ is second operand zero?
5320    beq     common_errDivideByZero
5321    .endif
5322    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5323
5324                               @ optional op; may set condition codes
5325    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5327    SET_VREG(r0, r9)               @ vAA<- r0
5328    GOTO_OPCODE(ip)                     @ jump to next instruction
5329    /* 10-13 instructions */
5330
5331
5332
5333/* ------------------------------ */
5334    .balign 64
5335.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5336/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5337/* File: armv6t2/binop2addr.S */
5338    /*
5339     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5340     * that specifies an instruction that performs "result = r0 op r1".
5341     * This could be an ARM instruction or a function call.  (If the result
5342     * comes back in a register other than r0, you can override "result".)
5343     *
5344     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5345     * vCC (r1).  Useful for integer division and modulus.
5346     *
5347     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5348     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5349     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5350     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5351     */
5352    /* binop/2addr vA, vB */
5353    mov     r3, rINST, lsr #12          @ r3<- B
5354    ubfx    r9, rINST, #8, #4           @ r9<- A
5355    GET_VREG(r1, r3)                    @ r1<- vB
5356    GET_VREG(r0, r9)                    @ r0<- vA
5357    .if 0
5358    cmp     r1, #0                      @ is second operand zero?
5359    beq     common_errDivideByZero
5360    .endif
5361    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5362
5363                               @ optional op; may set condition codes
5364    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5365    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5366    SET_VREG(r0, r9)               @ vAA<- r0
5367    GOTO_OPCODE(ip)                     @ jump to next instruction
5368    /* 10-13 instructions */
5369
5370
5371
5372/* ------------------------------ */
5373    .balign 64
5374.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5375/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5376/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5377/* File: armv6t2/binop2addr.S */
5378    /*
5379     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5380     * that specifies an instruction that performs "result = r0 op r1".
5381     * This could be an ARM instruction or a function call.  (If the result
5382     * comes back in a register other than r0, you can override "result".)
5383     *
5384     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5385     * vCC (r1).  Useful for integer division and modulus.
5386     *
5387     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5388     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5389     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5390     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5391     */
5392    /* binop/2addr vA, vB */
5393    mov     r3, rINST, lsr #12          @ r3<- B
5394    ubfx    r9, rINST, #8, #4           @ r9<- A
5395    GET_VREG(r1, r3)                    @ r1<- vB
5396    GET_VREG(r0, r9)                    @ r0<- vA
5397    .if 0
5398    cmp     r1, #0                      @ is second operand zero?
5399    beq     common_errDivideByZero
5400    .endif
5401    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5402
5403                               @ optional op; may set condition codes
5404    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5406    SET_VREG(r0, r9)               @ vAA<- r0
5407    GOTO_OPCODE(ip)                     @ jump to next instruction
5408    /* 10-13 instructions */
5409
5410
5411
5412/* ------------------------------ */
5413    .balign 64
5414.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5415/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5416/* File: armv6t2/binop2addr.S */
5417    /*
5418     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5419     * that specifies an instruction that performs "result = r0 op r1".
5420     * This could be an ARM instruction or a function call.  (If the result
5421     * comes back in a register other than r0, you can override "result".)
5422     *
5423     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5424     * vCC (r1).  Useful for integer division and modulus.
5425     *
5426     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5427     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5428     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5429     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5430     */
5431    /* binop/2addr vA, vB */
5432    mov     r3, rINST, lsr #12          @ r3<- B
5433    ubfx    r9, rINST, #8, #4           @ r9<- A
5434    GET_VREG(r1, r3)                    @ r1<- vB
5435    GET_VREG(r0, r9)                    @ r0<- vA
5436    .if 1
5437    cmp     r1, #0                      @ is second operand zero?
5438    beq     common_errDivideByZero
5439    .endif
5440    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5441
5442                               @ optional op; may set condition codes
5443    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5444    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5445    SET_VREG(r0, r9)               @ vAA<- r0
5446    GOTO_OPCODE(ip)                     @ jump to next instruction
5447    /* 10-13 instructions */
5448
5449
5450
5451/* ------------------------------ */
5452    .balign 64
5453.L_OP_REM_INT_2ADDR: /* 0xb4 */
5454/* File: armv6t2/OP_REM_INT_2ADDR.S */
5455/* idivmod returns quotient in r0 and remainder in r1 */
5456/* File: armv6t2/binop2addr.S */
5457    /*
5458     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5459     * that specifies an instruction that performs "result = r0 op r1".
5460     * This could be an ARM instruction or a function call.  (If the result
5461     * comes back in a register other than r0, you can override "result".)
5462     *
5463     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5464     * vCC (r1).  Useful for integer division and modulus.
5465     *
5466     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5467     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5468     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5469     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5470     */
5471    /* binop/2addr vA, vB */
5472    mov     r3, rINST, lsr #12          @ r3<- B
5473    ubfx    r9, rINST, #8, #4           @ r9<- A
5474    GET_VREG(r1, r3)                    @ r1<- vB
5475    GET_VREG(r0, r9)                    @ r0<- vA
5476    .if 1
5477    cmp     r1, #0                      @ is second operand zero?
5478    beq     common_errDivideByZero
5479    .endif
5480    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5481
5482                               @ optional op; may set condition codes
5483    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5484    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5485    SET_VREG(r1, r9)               @ vAA<- r1
5486    GOTO_OPCODE(ip)                     @ jump to next instruction
5487    /* 10-13 instructions */
5488
5489
5490
5491/* ------------------------------ */
5492    .balign 64
5493.L_OP_AND_INT_2ADDR: /* 0xb5 */
5494/* File: armv6t2/OP_AND_INT_2ADDR.S */
5495/* File: armv6t2/binop2addr.S */
5496    /*
5497     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5498     * that specifies an instruction that performs "result = r0 op r1".
5499     * This could be an ARM instruction or a function call.  (If the result
5500     * comes back in a register other than r0, you can override "result".)
5501     *
5502     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5503     * vCC (r1).  Useful for integer division and modulus.
5504     *
5505     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5506     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5507     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5508     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5509     */
5510    /* binop/2addr vA, vB */
5511    mov     r3, rINST, lsr #12          @ r3<- B
5512    ubfx    r9, rINST, #8, #4           @ r9<- A
5513    GET_VREG(r1, r3)                    @ r1<- vB
5514    GET_VREG(r0, r9)                    @ r0<- vA
5515    .if 0
5516    cmp     r1, #0                      @ is second operand zero?
5517    beq     common_errDivideByZero
5518    .endif
5519    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5520
5521                               @ optional op; may set condition codes
5522    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5523    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5524    SET_VREG(r0, r9)               @ vAA<- r0
5525    GOTO_OPCODE(ip)                     @ jump to next instruction
5526    /* 10-13 instructions */
5527
5528
5529
5530/* ------------------------------ */
5531    .balign 64
5532.L_OP_OR_INT_2ADDR: /* 0xb6 */
5533/* File: armv6t2/OP_OR_INT_2ADDR.S */
5534/* File: armv6t2/binop2addr.S */
5535    /*
5536     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5537     * that specifies an instruction that performs "result = r0 op r1".
5538     * This could be an ARM instruction or a function call.  (If the result
5539     * comes back in a register other than r0, you can override "result".)
5540     *
5541     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5542     * vCC (r1).  Useful for integer division and modulus.
5543     *
5544     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5545     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5546     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5547     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5548     */
5549    /* binop/2addr vA, vB */
5550    mov     r3, rINST, lsr #12          @ r3<- B
5551    ubfx    r9, rINST, #8, #4           @ r9<- A
5552    GET_VREG(r1, r3)                    @ r1<- vB
5553    GET_VREG(r0, r9)                    @ r0<- vA
5554    .if 0
5555    cmp     r1, #0                      @ is second operand zero?
5556    beq     common_errDivideByZero
5557    .endif
5558    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5559
5560                               @ optional op; may set condition codes
5561    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5562    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5563    SET_VREG(r0, r9)               @ vAA<- r0
5564    GOTO_OPCODE(ip)                     @ jump to next instruction
5565    /* 10-13 instructions */
5566
5567
5568
5569/* ------------------------------ */
5570    .balign 64
5571.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5572/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5573/* File: armv6t2/binop2addr.S */
5574    /*
5575     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5576     * that specifies an instruction that performs "result = r0 op r1".
5577     * This could be an ARM instruction or a function call.  (If the result
5578     * comes back in a register other than r0, you can override "result".)
5579     *
5580     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5581     * vCC (r1).  Useful for integer division and modulus.
5582     *
5583     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5584     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5585     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5586     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5587     */
5588    /* binop/2addr vA, vB */
5589    mov     r3, rINST, lsr #12          @ r3<- B
5590    ubfx    r9, rINST, #8, #4           @ r9<- A
5591    GET_VREG(r1, r3)                    @ r1<- vB
5592    GET_VREG(r0, r9)                    @ r0<- vA
5593    .if 0
5594    cmp     r1, #0                      @ is second operand zero?
5595    beq     common_errDivideByZero
5596    .endif
5597    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5598
5599                               @ optional op; may set condition codes
5600    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5601    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5602    SET_VREG(r0, r9)               @ vAA<- r0
5603    GOTO_OPCODE(ip)                     @ jump to next instruction
5604    /* 10-13 instructions */
5605
5606
5607
5608/* ------------------------------ */
5609    .balign 64
5610.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5611/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5612/* File: armv6t2/binop2addr.S */
5613    /*
5614     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5615     * that specifies an instruction that performs "result = r0 op r1".
5616     * This could be an ARM instruction or a function call.  (If the result
5617     * comes back in a register other than r0, you can override "result".)
5618     *
5619     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5620     * vCC (r1).  Useful for integer division and modulus.
5621     *
5622     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5623     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5624     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5625     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5626     */
5627    /* binop/2addr vA, vB */
5628    mov     r3, rINST, lsr #12          @ r3<- B
5629    ubfx    r9, rINST, #8, #4           @ r9<- A
5630    GET_VREG(r1, r3)                    @ r1<- vB
5631    GET_VREG(r0, r9)                    @ r0<- vA
5632    .if 0
5633    cmp     r1, #0                      @ is second operand zero?
5634    beq     common_errDivideByZero
5635    .endif
5636    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5637
5638    and     r1, r1, #31                           @ optional op; may set condition codes
5639    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5641    SET_VREG(r0, r9)               @ vAA<- r0
5642    GOTO_OPCODE(ip)                     @ jump to next instruction
5643    /* 10-13 instructions */
5644
5645
5646
5647/* ------------------------------ */
5648    .balign 64
5649.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5650/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5651/* File: armv6t2/binop2addr.S */
5652    /*
5653     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5654     * that specifies an instruction that performs "result = r0 op r1".
5655     * This could be an ARM instruction or a function call.  (If the result
5656     * comes back in a register other than r0, you can override "result".)
5657     *
5658     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5659     * vCC (r1).  Useful for integer division and modulus.
5660     *
5661     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5662     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5663     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5664     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5665     */
5666    /* binop/2addr vA, vB */
5667    mov     r3, rINST, lsr #12          @ r3<- B
5668    ubfx    r9, rINST, #8, #4           @ r9<- A
5669    GET_VREG(r1, r3)                    @ r1<- vB
5670    GET_VREG(r0, r9)                    @ r0<- vA
5671    .if 0
5672    cmp     r1, #0                      @ is second operand zero?
5673    beq     common_errDivideByZero
5674    .endif
5675    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5676
5677    and     r1, r1, #31                           @ optional op; may set condition codes
5678    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5680    SET_VREG(r0, r9)               @ vAA<- r0
5681    GOTO_OPCODE(ip)                     @ jump to next instruction
5682    /* 10-13 instructions */
5683
5684
5685
5686/* ------------------------------ */
5687    .balign 64
5688.L_OP_USHR_INT_2ADDR: /* 0xba */
5689/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5690/* File: armv6t2/binop2addr.S */
5691    /*
5692     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5693     * that specifies an instruction that performs "result = r0 op r1".
5694     * This could be an ARM instruction or a function call.  (If the result
5695     * comes back in a register other than r0, you can override "result".)
5696     *
5697     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5698     * vCC (r1).  Useful for integer division and modulus.
5699     *
5700     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5701     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5702     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5703     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5704     */
5705    /* binop/2addr vA, vB */
5706    mov     r3, rINST, lsr #12          @ r3<- B
5707    ubfx    r9, rINST, #8, #4           @ r9<- A
5708    GET_VREG(r1, r3)                    @ r1<- vB
5709    GET_VREG(r0, r9)                    @ r0<- vA
5710    .if 0
5711    cmp     r1, #0                      @ is second operand zero?
5712    beq     common_errDivideByZero
5713    .endif
5714    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5715
5716    and     r1, r1, #31                           @ optional op; may set condition codes
5717    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5719    SET_VREG(r0, r9)               @ vAA<- r0
5720    GOTO_OPCODE(ip)                     @ jump to next instruction
5721    /* 10-13 instructions */
5722
5723
5724
5725/* ------------------------------ */
5726    .balign 64
5727.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5728/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5729/* File: armv6t2/binopWide2addr.S */
5730    /*
5731     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5732     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5733     * This could be an ARM instruction or a function call.  (If the result
5734     * comes back in a register other than r0, you can override "result".)
5735     *
5736     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5737     * vCC (r1).  Useful for integer division and modulus.
5738     *
5739     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5740     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5741     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5742     *      rem-double/2addr
5743     */
5744    /* binop/2addr vA, vB */
5745    mov     r1, rINST, lsr #12          @ r1<- B
5746    ubfx    r9, rINST, #8, #4           @ r9<- A
5747    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5748    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5749    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5750    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5751    .if 0
5752    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5753    beq     common_errDivideByZero
5754    .endif
5755    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5756
5757    adds    r0, r0, r2                           @ optional op; may set condition codes
5758    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5760    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5761    GOTO_OPCODE(ip)                     @ jump to next instruction
5762    /* 12-15 instructions */
5763
5764
5765
5766/* ------------------------------ */
5767    .balign 64
5768.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5769/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5770/* File: armv6t2/binopWide2addr.S */
5771    /*
5772     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5773     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5774     * This could be an ARM instruction or a function call.  (If the result
5775     * comes back in a register other than r0, you can override "result".)
5776     *
5777     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5778     * vCC (r1).  Useful for integer division and modulus.
5779     *
5780     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5781     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5782     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5783     *      rem-double/2addr
5784     */
5785    /* binop/2addr vA, vB */
5786    mov     r1, rINST, lsr #12          @ r1<- B
5787    ubfx    r9, rINST, #8, #4           @ r9<- A
5788    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5789    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5790    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5791    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5792    .if 0
5793    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5794    beq     common_errDivideByZero
5795    .endif
5796    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5797
5798    subs    r0, r0, r2                           @ optional op; may set condition codes
5799    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5801    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5802    GOTO_OPCODE(ip)                     @ jump to next instruction
5803    /* 12-15 instructions */
5804
5805
5806
5807/* ------------------------------ */
5808    .balign 64
5809.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5810/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5811    /*
5812     * Signed 64-bit integer multiply, "/2addr" version.
5813     *
5814     * See OP_MUL_LONG for an explanation.
5815     *
5816     * We get a little tight on registers, so to avoid looking up &fp[A]
5817     * again we stuff it into rINST.
5818     */
5819    /* mul-long/2addr vA, vB */
5820    mov     r1, rINST, lsr #12          @ r1<- B
5821    ubfx    r9, rINST, #8, #4           @ r9<- A
5822    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5823    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5824    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5825    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5826    mul     ip, r2, r1                  @  ip<- ZxW
5827    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5828    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5829    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5830    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5831    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5833    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5834    GOTO_OPCODE(ip)                     @ jump to next instruction
5835
5836
5837/* ------------------------------ */
5838    .balign 64
5839.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5840/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5841/* File: armv6t2/binopWide2addr.S */
5842    /*
5843     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5844     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5845     * This could be an ARM instruction or a function call.  (If the result
5846     * comes back in a register other than r0, you can override "result".)
5847     *
5848     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5849     * vCC (r1).  Useful for integer division and modulus.
5850     *
5851     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5852     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5853     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5854     *      rem-double/2addr
5855     */
5856    /* binop/2addr vA, vB */
5857    mov     r1, rINST, lsr #12          @ r1<- B
5858    ubfx    r9, rINST, #8, #4           @ r9<- A
5859    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5860    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5861    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5862    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5863    .if 1
5864    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5865    beq     common_errDivideByZero
5866    .endif
5867    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5868
5869                               @ optional op; may set condition codes
5870    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5871    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5872    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5873    GOTO_OPCODE(ip)                     @ jump to next instruction
5874    /* 12-15 instructions */
5875
5876
5877
5878/* ------------------------------ */
5879    .balign 64
5880.L_OP_REM_LONG_2ADDR: /* 0xbf */
5881/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5882/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5883/* File: armv6t2/binopWide2addr.S */
5884    /*
5885     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5886     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5887     * This could be an ARM instruction or a function call.  (If the result
5888     * comes back in a register other than r0, you can override "result".)
5889     *
5890     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5891     * vCC (r1).  Useful for integer division and modulus.
5892     *
5893     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5894     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5895     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5896     *      rem-double/2addr
5897     */
5898    /* binop/2addr vA, vB */
5899    mov     r1, rINST, lsr #12          @ r1<- B
5900    ubfx    r9, rINST, #8, #4           @ r9<- A
5901    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5902    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5903    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5904    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5905    .if 1
5906    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5907    beq     common_errDivideByZero
5908    .endif
5909    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5910
5911                               @ optional op; may set condition codes
5912    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5913    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5914    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5915    GOTO_OPCODE(ip)                     @ jump to next instruction
5916    /* 12-15 instructions */
5917
5918
5919
5920/* ------------------------------ */
5921    .balign 64
5922.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5923/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5924/* File: armv6t2/binopWide2addr.S */
5925    /*
5926     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5927     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5928     * This could be an ARM instruction or a function call.  (If the result
5929     * comes back in a register other than r0, you can override "result".)
5930     *
5931     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5932     * vCC (r1).  Useful for integer division and modulus.
5933     *
5934     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5935     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5936     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5937     *      rem-double/2addr
5938     */
5939    /* binop/2addr vA, vB */
5940    mov     r1, rINST, lsr #12          @ r1<- B
5941    ubfx    r9, rINST, #8, #4           @ r9<- A
5942    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5943    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5944    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5945    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5946    .if 0
5947    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5948    beq     common_errDivideByZero
5949    .endif
5950    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5951
5952    and     r0, r0, r2                           @ optional op; may set condition codes
5953    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5955    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5956    GOTO_OPCODE(ip)                     @ jump to next instruction
5957    /* 12-15 instructions */
5958
5959
5960
5961/* ------------------------------ */
5962    .balign 64
5963.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5964/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5965/* File: armv6t2/binopWide2addr.S */
5966    /*
5967     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5968     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5969     * This could be an ARM instruction or a function call.  (If the result
5970     * comes back in a register other than r0, you can override "result".)
5971     *
5972     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5973     * vCC (r1).  Useful for integer division and modulus.
5974     *
5975     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5976     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5977     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5978     *      rem-double/2addr
5979     */
5980    /* binop/2addr vA, vB */
5981    mov     r1, rINST, lsr #12          @ r1<- B
5982    ubfx    r9, rINST, #8, #4           @ r9<- A
5983    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5984    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5985    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5986    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5987    .if 0
5988    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5989    beq     common_errDivideByZero
5990    .endif
5991    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5992
5993    orr     r0, r0, r2                           @ optional op; may set condition codes
5994    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5995    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5996    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5997    GOTO_OPCODE(ip)                     @ jump to next instruction
5998    /* 12-15 instructions */
5999
6000
6001
6002/* ------------------------------ */
6003    .balign 64
6004.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6005/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
6006/* File: armv6t2/binopWide2addr.S */
6007    /*
6008     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6009     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6010     * This could be an ARM instruction or a function call.  (If the result
6011     * comes back in a register other than r0, you can override "result".)
6012     *
6013     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6014     * vCC (r1).  Useful for integer division and modulus.
6015     *
6016     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6017     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6018     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6019     *      rem-double/2addr
6020     */
6021    /* binop/2addr vA, vB */
6022    mov     r1, rINST, lsr #12          @ r1<- B
6023    ubfx    r9, rINST, #8, #4           @ r9<- A
6024    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6025    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6026    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6027    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6028    .if 0
6029    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6030    beq     common_errDivideByZero
6031    .endif
6032    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6033
6034    eor     r0, r0, r2                           @ optional op; may set condition codes
6035    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6037    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6038    GOTO_OPCODE(ip)                     @ jump to next instruction
6039    /* 12-15 instructions */
6040
6041
6042
6043/* ------------------------------ */
6044    .balign 64
6045.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6046/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
6047    /*
6048     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6049     * 32-bit shift distance.
6050     */
6051    /* shl-long/2addr vA, vB */
6052    mov     r3, rINST, lsr #12          @ r3<- B
6053    ubfx    r9, rINST, #8, #4           @ r9<- A
6054    GET_VREG(r2, r3)                    @ r2<- vB
6055    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6056    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6057    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6058
6059    mov     r1, r1, asl r2              @  r1<- r1 << r2
6060    rsb     r3, r2, #32                 @  r3<- 32 - r2
6061    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6062    subs    ip, r2, #32                 @  ip<- r2 - 32
6063    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6064    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6065    mov     r0, r0, asl r2              @  r0<- r0 << r2
6066    b       .LOP_SHL_LONG_2ADDR_finish
6067
6068/* ------------------------------ */
6069    .balign 64
6070.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6071/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6072    /*
6073     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6074     * 32-bit shift distance.
6075     */
6076    /* shr-long/2addr vA, vB */
6077    mov     r3, rINST, lsr #12          @ r3<- B
6078    ubfx    r9, rINST, #8, #4           @ r9<- A
6079    GET_VREG(r2, r3)                    @ r2<- vB
6080    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6081    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6082    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6083
6084    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6085    rsb     r3, r2, #32                 @  r3<- 32 - r2
6086    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6087    subs    ip, r2, #32                 @  ip<- r2 - 32
6088    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6089    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6090    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6091    b       .LOP_SHR_LONG_2ADDR_finish
6092
6093/* ------------------------------ */
6094    .balign 64
6095.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6096/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6097    /*
6098     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6099     * 32-bit shift distance.
6100     */
6101    /* ushr-long/2addr vA, vB */
6102    mov     r3, rINST, lsr #12          @ r3<- B
6103    ubfx    r9, rINST, #8, #4           @ r9<- A
6104    GET_VREG(r2, r3)                    @ r2<- vB
6105    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6106    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6107    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6108
6109    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6110    rsb     r3, r2, #32                 @  r3<- 32 - r2
6111    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6112    subs    ip, r2, #32                 @  ip<- r2 - 32
6113    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6114    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6115    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6116    b       .LOP_USHR_LONG_2ADDR_finish
6117
6118/* ------------------------------ */
6119    .balign 64
6120.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6121/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6122/* File: arm-vfp/fbinop2addr.S */
6123    /*
6124     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6125     * an "instr" line that specifies an instruction that performs
6126     * "s2 = s0 op s1".
6127     *
6128     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6129     */
6130    /* binop/2addr vA, vB */
6131    mov     r3, rINST, lsr #12          @ r3<- B
6132    mov     r9, rINST, lsr #8           @ r9<- A+
6133    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6134    and     r9, r9, #15                 @ r9<- A
6135    flds    s1, [r3]                    @ s1<- vB
6136    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6137    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6138    flds    s0, [r9]                    @ s0<- vA
6139
6140    fadds   s2, s0, s1                              @ s2<- op
6141    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6142    fsts    s2, [r9]                    @ vAA<- s2
6143    GOTO_OPCODE(ip)                     @ jump to next instruction
6144
6145
6146/* ------------------------------ */
6147    .balign 64
6148.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6149/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6150/* File: arm-vfp/fbinop2addr.S */
6151    /*
6152     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6153     * an "instr" line that specifies an instruction that performs
6154     * "s2 = s0 op s1".
6155     *
6156     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6157     */
6158    /* binop/2addr vA, vB */
6159    mov     r3, rINST, lsr #12          @ r3<- B
6160    mov     r9, rINST, lsr #8           @ r9<- A+
6161    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6162    and     r9, r9, #15                 @ r9<- A
6163    flds    s1, [r3]                    @ s1<- vB
6164    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6165    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6166    flds    s0, [r9]                    @ s0<- vA
6167
6168    fsubs   s2, s0, s1                              @ s2<- op
6169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6170    fsts    s2, [r9]                    @ vAA<- s2
6171    GOTO_OPCODE(ip)                     @ jump to next instruction
6172
6173
6174/* ------------------------------ */
6175    .balign 64
6176.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6177/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6178/* File: arm-vfp/fbinop2addr.S */
6179    /*
6180     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6181     * an "instr" line that specifies an instruction that performs
6182     * "s2 = s0 op s1".
6183     *
6184     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6185     */
6186    /* binop/2addr vA, vB */
6187    mov     r3, rINST, lsr #12          @ r3<- B
6188    mov     r9, rINST, lsr #8           @ r9<- A+
6189    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6190    and     r9, r9, #15                 @ r9<- A
6191    flds    s1, [r3]                    @ s1<- vB
6192    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6193    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6194    flds    s0, [r9]                    @ s0<- vA
6195
6196    fmuls   s2, s0, s1                              @ s2<- op
6197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6198    fsts    s2, [r9]                    @ vAA<- s2
6199    GOTO_OPCODE(ip)                     @ jump to next instruction
6200
6201
6202/* ------------------------------ */
6203    .balign 64
6204.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6205/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6206/* File: arm-vfp/fbinop2addr.S */
6207    /*
6208     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6209     * an "instr" line that specifies an instruction that performs
6210     * "s2 = s0 op s1".
6211     *
6212     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6213     */
6214    /* binop/2addr vA, vB */
6215    mov     r3, rINST, lsr #12          @ r3<- B
6216    mov     r9, rINST, lsr #8           @ r9<- A+
6217    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6218    and     r9, r9, #15                 @ r9<- A
6219    flds    s1, [r3]                    @ s1<- vB
6220    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6221    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6222    flds    s0, [r9]                    @ s0<- vA
6223
6224    fdivs   s2, s0, s1                              @ s2<- op
6225    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6226    fsts    s2, [r9]                    @ vAA<- s2
6227    GOTO_OPCODE(ip)                     @ jump to next instruction
6228
6229
6230/* ------------------------------ */
6231    .balign 64
6232.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6233/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6234/* EABI doesn't define a float remainder function, but libm does */
6235/* File: armv6t2/binop2addr.S */
6236    /*
6237     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6238     * that specifies an instruction that performs "result = r0 op r1".
6239     * This could be an ARM instruction or a function call.  (If the result
6240     * comes back in a register other than r0, you can override "result".)
6241     *
6242     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6243     * vCC (r1).  Useful for integer division and modulus.
6244     *
6245     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6246     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6247     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6248     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6249     */
6250    /* binop/2addr vA, vB */
6251    mov     r3, rINST, lsr #12          @ r3<- B
6252    ubfx    r9, rINST, #8, #4           @ r9<- A
6253    GET_VREG(r1, r3)                    @ r1<- vB
6254    GET_VREG(r0, r9)                    @ r0<- vA
6255    .if 0
6256    cmp     r1, #0                      @ is second operand zero?
6257    beq     common_errDivideByZero
6258    .endif
6259    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6260
6261                               @ optional op; may set condition codes
6262    bl      fmodf                              @ r0<- op, r0-r3 changed
6263    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6264    SET_VREG(r0, r9)               @ vAA<- r0
6265    GOTO_OPCODE(ip)                     @ jump to next instruction
6266    /* 10-13 instructions */
6267
6268
6269
6270/* ------------------------------ */
6271    .balign 64
6272.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6273/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6274/* File: arm-vfp/fbinopWide2addr.S */
6275    /*
6276     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6277     * an "instr" line that specifies an instruction that performs
6278     * "d2 = d0 op d1".
6279     *
6280     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6281     *      div-double/2addr
6282     */
6283    /* binop/2addr vA, vB */
6284    mov     r3, rINST, lsr #12          @ r3<- B
6285    mov     r9, rINST, lsr #8           @ r9<- A+
6286    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6287    and     r9, r9, #15                 @ r9<- A
6288    fldd    d1, [r3]                    @ d1<- vB
6289    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6290    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6291    fldd    d0, [r9]                    @ d0<- vA
6292
6293    faddd   d2, d0, d1                              @ d2<- op
6294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6295    fstd    d2, [r9]                    @ vAA<- d2
6296    GOTO_OPCODE(ip)                     @ jump to next instruction
6297
6298
6299/* ------------------------------ */
6300    .balign 64
6301.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6302/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6303/* File: arm-vfp/fbinopWide2addr.S */
6304    /*
6305     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6306     * an "instr" line that specifies an instruction that performs
6307     * "d2 = d0 op d1".
6308     *
6309     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6310     *      div-double/2addr
6311     */
6312    /* binop/2addr vA, vB */
6313    mov     r3, rINST, lsr #12          @ r3<- B
6314    mov     r9, rINST, lsr #8           @ r9<- A+
6315    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6316    and     r9, r9, #15                 @ r9<- A
6317    fldd    d1, [r3]                    @ d1<- vB
6318    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6319    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6320    fldd    d0, [r9]                    @ d0<- vA
6321
6322    fsubd   d2, d0, d1                              @ d2<- op
6323    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6324    fstd    d2, [r9]                    @ vAA<- d2
6325    GOTO_OPCODE(ip)                     @ jump to next instruction
6326
6327
6328/* ------------------------------ */
6329    .balign 64
6330.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6331/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6332/* File: arm-vfp/fbinopWide2addr.S */
6333    /*
6334     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6335     * an "instr" line that specifies an instruction that performs
6336     * "d2 = d0 op d1".
6337     *
6338     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6339     *      div-double/2addr
6340     */
6341    /* binop/2addr vA, vB */
6342    mov     r3, rINST, lsr #12          @ r3<- B
6343    mov     r9, rINST, lsr #8           @ r9<- A+
6344    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6345    and     r9, r9, #15                 @ r9<- A
6346    fldd    d1, [r3]                    @ d1<- vB
6347    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6348    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6349    fldd    d0, [r9]                    @ d0<- vA
6350
6351    fmuld   d2, d0, d1                              @ d2<- op
6352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6353    fstd    d2, [r9]                    @ vAA<- d2
6354    GOTO_OPCODE(ip)                     @ jump to next instruction
6355
6356
6357/* ------------------------------ */
6358    .balign 64
6359.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6360/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6361/* File: arm-vfp/fbinopWide2addr.S */
6362    /*
6363     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6364     * an "instr" line that specifies an instruction that performs
6365     * "d2 = d0 op d1".
6366     *
6367     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6368     *      div-double/2addr
6369     */
6370    /* binop/2addr vA, vB */
6371    mov     r3, rINST, lsr #12          @ r3<- B
6372    mov     r9, rINST, lsr #8           @ r9<- A+
6373    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6374    and     r9, r9, #15                 @ r9<- A
6375    fldd    d1, [r3]                    @ d1<- vB
6376    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6377    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6378    fldd    d0, [r9]                    @ d0<- vA
6379
6380    fdivd   d2, d0, d1                              @ d2<- op
6381    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6382    fstd    d2, [r9]                    @ vAA<- d2
6383    GOTO_OPCODE(ip)                     @ jump to next instruction
6384
6385
6386/* ------------------------------ */
6387    .balign 64
6388.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6389/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6390/* EABI doesn't define a double remainder function, but libm does */
6391/* File: armv6t2/binopWide2addr.S */
6392    /*
6393     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6394     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6395     * This could be an ARM instruction or a function call.  (If the result
6396     * comes back in a register other than r0, you can override "result".)
6397     *
6398     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6399     * vCC (r1).  Useful for integer division and modulus.
6400     *
6401     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6402     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6403     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6404     *      rem-double/2addr
6405     */
6406    /* binop/2addr vA, vB */
6407    mov     r1, rINST, lsr #12          @ r1<- B
6408    ubfx    r9, rINST, #8, #4           @ r9<- A
6409    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6410    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6411    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6412    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6413    .if 0
6414    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6415    beq     common_errDivideByZero
6416    .endif
6417    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6418
6419                               @ optional op; may set condition codes
6420    bl      fmod                              @ result<- op, r0-r3 changed
6421    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6422    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6423    GOTO_OPCODE(ip)                     @ jump to next instruction
6424    /* 12-15 instructions */
6425
6426
6427
6428/* ------------------------------ */
6429    .balign 64
6430.L_OP_ADD_INT_LIT16: /* 0xd0 */
6431/* File: armv6t2/OP_ADD_INT_LIT16.S */
6432/* File: armv6t2/binopLit16.S */
6433    /*
6434     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6435     * that specifies an instruction that performs "result = r0 op r1".
6436     * This could be an ARM instruction or a function call.  (If the result
6437     * comes back in a register other than r0, you can override "result".)
6438     *
6439     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6440     * vCC (r1).  Useful for integer division and modulus.
6441     *
6442     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6443     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6444     */
6445    /* binop/lit16 vA, vB, #+CCCC */
6446    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6447    mov     r2, rINST, lsr #12          @ r2<- B
6448    ubfx    r9, rINST, #8, #4           @ r9<- A
6449    GET_VREG(r0, r2)                    @ r0<- vB
6450    .if 0
6451    cmp     r1, #0                      @ is second operand zero?
6452    beq     common_errDivideByZero
6453    .endif
6454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6455
6456    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6458    SET_VREG(r0, r9)               @ vAA<- r0
6459    GOTO_OPCODE(ip)                     @ jump to next instruction
6460    /* 10-13 instructions */
6461
6462
6463
6464/* ------------------------------ */
6465    .balign 64
6466.L_OP_RSUB_INT: /* 0xd1 */
6467/* File: armv6t2/OP_RSUB_INT.S */
6468/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6469/* File: armv6t2/binopLit16.S */
6470    /*
6471     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6472     * that specifies an instruction that performs "result = r0 op r1".
6473     * This could be an ARM instruction or a function call.  (If the result
6474     * comes back in a register other than r0, you can override "result".)
6475     *
6476     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6477     * vCC (r1).  Useful for integer division and modulus.
6478     *
6479     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6480     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6481     */
6482    /* binop/lit16 vA, vB, #+CCCC */
6483    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6484    mov     r2, rINST, lsr #12          @ r2<- B
6485    ubfx    r9, rINST, #8, #4           @ r9<- A
6486    GET_VREG(r0, r2)                    @ r0<- vB
6487    .if 0
6488    cmp     r1, #0                      @ is second operand zero?
6489    beq     common_errDivideByZero
6490    .endif
6491    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6492
6493    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6494    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6495    SET_VREG(r0, r9)               @ vAA<- r0
6496    GOTO_OPCODE(ip)                     @ jump to next instruction
6497    /* 10-13 instructions */
6498
6499
6500
6501/* ------------------------------ */
6502    .balign 64
6503.L_OP_MUL_INT_LIT16: /* 0xd2 */
6504/* File: armv6t2/OP_MUL_INT_LIT16.S */
6505/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6506/* File: armv6t2/binopLit16.S */
6507    /*
6508     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6509     * that specifies an instruction that performs "result = r0 op r1".
6510     * This could be an ARM instruction or a function call.  (If the result
6511     * comes back in a register other than r0, you can override "result".)
6512     *
6513     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6514     * vCC (r1).  Useful for integer division and modulus.
6515     *
6516     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6517     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6518     */
6519    /* binop/lit16 vA, vB, #+CCCC */
6520    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6521    mov     r2, rINST, lsr #12          @ r2<- B
6522    ubfx    r9, rINST, #8, #4           @ r9<- A
6523    GET_VREG(r0, r2)                    @ r0<- vB
6524    .if 0
6525    cmp     r1, #0                      @ is second operand zero?
6526    beq     common_errDivideByZero
6527    .endif
6528    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6529
6530    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6532    SET_VREG(r0, r9)               @ vAA<- r0
6533    GOTO_OPCODE(ip)                     @ jump to next instruction
6534    /* 10-13 instructions */
6535
6536
6537
6538/* ------------------------------ */
6539    .balign 64
6540.L_OP_DIV_INT_LIT16: /* 0xd3 */
6541/* File: armv6t2/OP_DIV_INT_LIT16.S */
6542/* File: armv6t2/binopLit16.S */
6543    /*
6544     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6545     * that specifies an instruction that performs "result = r0 op r1".
6546     * This could be an ARM instruction or a function call.  (If the result
6547     * comes back in a register other than r0, you can override "result".)
6548     *
6549     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6550     * vCC (r1).  Useful for integer division and modulus.
6551     *
6552     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6553     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6554     */
6555    /* binop/lit16 vA, vB, #+CCCC */
6556    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6557    mov     r2, rINST, lsr #12          @ r2<- B
6558    ubfx    r9, rINST, #8, #4           @ r9<- A
6559    GET_VREG(r0, r2)                    @ r0<- vB
6560    .if 1
6561    cmp     r1, #0                      @ is second operand zero?
6562    beq     common_errDivideByZero
6563    .endif
6564    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6565
6566    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6568    SET_VREG(r0, r9)               @ vAA<- r0
6569    GOTO_OPCODE(ip)                     @ jump to next instruction
6570    /* 10-13 instructions */
6571
6572
6573
6574/* ------------------------------ */
6575    .balign 64
6576.L_OP_REM_INT_LIT16: /* 0xd4 */
6577/* File: armv6t2/OP_REM_INT_LIT16.S */
6578/* idivmod returns quotient in r0 and remainder in r1 */
6579/* File: armv6t2/binopLit16.S */
6580    /*
6581     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6582     * that specifies an instruction that performs "result = r0 op r1".
6583     * This could be an ARM instruction or a function call.  (If the result
6584     * comes back in a register other than r0, you can override "result".)
6585     *
6586     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6587     * vCC (r1).  Useful for integer division and modulus.
6588     *
6589     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6590     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6591     */
6592    /* binop/lit16 vA, vB, #+CCCC */
6593    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6594    mov     r2, rINST, lsr #12          @ r2<- B
6595    ubfx    r9, rINST, #8, #4           @ r9<- A
6596    GET_VREG(r0, r2)                    @ r0<- vB
6597    .if 1
6598    cmp     r1, #0                      @ is second operand zero?
6599    beq     common_errDivideByZero
6600    .endif
6601    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6602
6603    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6604    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6605    SET_VREG(r1, r9)               @ vAA<- r1
6606    GOTO_OPCODE(ip)                     @ jump to next instruction
6607    /* 10-13 instructions */
6608
6609
6610
6611/* ------------------------------ */
6612    .balign 64
6613.L_OP_AND_INT_LIT16: /* 0xd5 */
6614/* File: armv6t2/OP_AND_INT_LIT16.S */
6615/* File: armv6t2/binopLit16.S */
6616    /*
6617     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6618     * that specifies an instruction that performs "result = r0 op r1".
6619     * This could be an ARM instruction or a function call.  (If the result
6620     * comes back in a register other than r0, you can override "result".)
6621     *
6622     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6623     * vCC (r1).  Useful for integer division and modulus.
6624     *
6625     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6626     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6627     */
6628    /* binop/lit16 vA, vB, #+CCCC */
6629    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6630    mov     r2, rINST, lsr #12          @ r2<- B
6631    ubfx    r9, rINST, #8, #4           @ r9<- A
6632    GET_VREG(r0, r2)                    @ r0<- vB
6633    .if 0
6634    cmp     r1, #0                      @ is second operand zero?
6635    beq     common_errDivideByZero
6636    .endif
6637    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6638
6639    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6641    SET_VREG(r0, r9)               @ vAA<- r0
6642    GOTO_OPCODE(ip)                     @ jump to next instruction
6643    /* 10-13 instructions */
6644
6645
6646
6647/* ------------------------------ */
6648    .balign 64
6649.L_OP_OR_INT_LIT16: /* 0xd6 */
6650/* File: armv6t2/OP_OR_INT_LIT16.S */
6651/* File: armv6t2/binopLit16.S */
6652    /*
6653     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6654     * that specifies an instruction that performs "result = r0 op r1".
6655     * This could be an ARM instruction or a function call.  (If the result
6656     * comes back in a register other than r0, you can override "result".)
6657     *
6658     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6659     * vCC (r1).  Useful for integer division and modulus.
6660     *
6661     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6662     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6663     */
6664    /* binop/lit16 vA, vB, #+CCCC */
6665    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6666    mov     r2, rINST, lsr #12          @ r2<- B
6667    ubfx    r9, rINST, #8, #4           @ r9<- A
6668    GET_VREG(r0, r2)                    @ r0<- vB
6669    .if 0
6670    cmp     r1, #0                      @ is second operand zero?
6671    beq     common_errDivideByZero
6672    .endif
6673    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6674
6675    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6677    SET_VREG(r0, r9)               @ vAA<- r0
6678    GOTO_OPCODE(ip)                     @ jump to next instruction
6679    /* 10-13 instructions */
6680
6681
6682
6683/* ------------------------------ */
6684    .balign 64
6685.L_OP_XOR_INT_LIT16: /* 0xd7 */
6686/* File: armv6t2/OP_XOR_INT_LIT16.S */
6687/* File: armv6t2/binopLit16.S */
6688    /*
6689     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6690     * that specifies an instruction that performs "result = r0 op r1".
6691     * This could be an ARM instruction or a function call.  (If the result
6692     * comes back in a register other than r0, you can override "result".)
6693     *
6694     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6695     * vCC (r1).  Useful for integer division and modulus.
6696     *
6697     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6698     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6699     */
6700    /* binop/lit16 vA, vB, #+CCCC */
6701    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6702    mov     r2, rINST, lsr #12          @ r2<- B
6703    ubfx    r9, rINST, #8, #4           @ r9<- A
6704    GET_VREG(r0, r2)                    @ r0<- vB
6705    .if 0
6706    cmp     r1, #0                      @ is second operand zero?
6707    beq     common_errDivideByZero
6708    .endif
6709    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6710
6711    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6712    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6713    SET_VREG(r0, r9)               @ vAA<- r0
6714    GOTO_OPCODE(ip)                     @ jump to next instruction
6715    /* 10-13 instructions */
6716
6717
6718
6719/* ------------------------------ */
6720    .balign 64
6721.L_OP_ADD_INT_LIT8: /* 0xd8 */
6722/* File: armv5te/OP_ADD_INT_LIT8.S */
6723/* File: armv5te/binopLit8.S */
6724    /*
6725     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6726     * that specifies an instruction that performs "result = r0 op r1".
6727     * This could be an ARM instruction or a function call.  (If the result
6728     * comes back in a register other than r0, you can override "result".)
6729     *
6730     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6731     * vCC (r1).  Useful for integer division and modulus.
6732     *
6733     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6734     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6735     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6736     */
6737    /* binop/lit8 vAA, vBB, #+CC */
6738    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6739    mov     r9, rINST, lsr #8           @ r9<- AA
6740    and     r2, r3, #255                @ r2<- BB
6741    GET_VREG(r0, r2)                    @ r0<- vBB
6742    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6743    .if 0
6744    @cmp     r1, #0                      @ is second operand zero?
6745    beq     common_errDivideByZero
6746    .endif
6747    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6748
6749                               @ optional op; may set condition codes
6750    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6752    SET_VREG(r0, r9)               @ vAA<- r0
6753    GOTO_OPCODE(ip)                     @ jump to next instruction
6754    /* 10-12 instructions */
6755
6756
6757
6758/* ------------------------------ */
6759    .balign 64
6760.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6761/* File: armv5te/OP_RSUB_INT_LIT8.S */
6762/* File: armv5te/binopLit8.S */
6763    /*
6764     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6765     * that specifies an instruction that performs "result = r0 op r1".
6766     * This could be an ARM instruction or a function call.  (If the result
6767     * comes back in a register other than r0, you can override "result".)
6768     *
6769     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6770     * vCC (r1).  Useful for integer division and modulus.
6771     *
6772     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6773     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6774     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6775     */
6776    /* binop/lit8 vAA, vBB, #+CC */
6777    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6778    mov     r9, rINST, lsr #8           @ r9<- AA
6779    and     r2, r3, #255                @ r2<- BB
6780    GET_VREG(r0, r2)                    @ r0<- vBB
6781    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6782    .if 0
6783    @cmp     r1, #0                      @ is second operand zero?
6784    beq     common_errDivideByZero
6785    .endif
6786    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6787
6788                               @ optional op; may set condition codes
6789    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6791    SET_VREG(r0, r9)               @ vAA<- r0
6792    GOTO_OPCODE(ip)                     @ jump to next instruction
6793    /* 10-12 instructions */
6794
6795
6796
6797/* ------------------------------ */
6798    .balign 64
6799.L_OP_MUL_INT_LIT8: /* 0xda */
6800/* File: armv5te/OP_MUL_INT_LIT8.S */
6801/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6802/* File: armv5te/binopLit8.S */
6803    /*
6804     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6805     * that specifies an instruction that performs "result = r0 op r1".
6806     * This could be an ARM instruction or a function call.  (If the result
6807     * comes back in a register other than r0, you can override "result".)
6808     *
6809     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6810     * vCC (r1).  Useful for integer division and modulus.
6811     *
6812     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6813     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6814     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6815     */
6816    /* binop/lit8 vAA, vBB, #+CC */
6817    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6818    mov     r9, rINST, lsr #8           @ r9<- AA
6819    and     r2, r3, #255                @ r2<- BB
6820    GET_VREG(r0, r2)                    @ r0<- vBB
6821    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6822    .if 0
6823    @cmp     r1, #0                      @ is second operand zero?
6824    beq     common_errDivideByZero
6825    .endif
6826    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6827
6828                               @ optional op; may set condition codes
6829    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6831    SET_VREG(r0, r9)               @ vAA<- r0
6832    GOTO_OPCODE(ip)                     @ jump to next instruction
6833    /* 10-12 instructions */
6834
6835
6836
6837/* ------------------------------ */
6838    .balign 64
6839.L_OP_DIV_INT_LIT8: /* 0xdb */
6840/* File: armv5te/OP_DIV_INT_LIT8.S */
6841/* File: armv5te/binopLit8.S */
6842    /*
6843     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6844     * that specifies an instruction that performs "result = r0 op r1".
6845     * This could be an ARM instruction or a function call.  (If the result
6846     * comes back in a register other than r0, you can override "result".)
6847     *
6848     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6849     * vCC (r1).  Useful for integer division and modulus.
6850     *
6851     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6852     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6853     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6854     */
6855    /* binop/lit8 vAA, vBB, #+CC */
6856    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6857    mov     r9, rINST, lsr #8           @ r9<- AA
6858    and     r2, r3, #255                @ r2<- BB
6859    GET_VREG(r0, r2)                    @ r0<- vBB
6860    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6861    .if 1
6862    @cmp     r1, #0                      @ is second operand zero?
6863    beq     common_errDivideByZero
6864    .endif
6865    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6866
6867                               @ optional op; may set condition codes
6868    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6870    SET_VREG(r0, r9)               @ vAA<- r0
6871    GOTO_OPCODE(ip)                     @ jump to next instruction
6872    /* 10-12 instructions */
6873
6874
6875
6876/* ------------------------------ */
6877    .balign 64
6878.L_OP_REM_INT_LIT8: /* 0xdc */
6879/* File: armv5te/OP_REM_INT_LIT8.S */
6880/* idivmod returns quotient in r0 and remainder in r1 */
6881/* File: armv5te/binopLit8.S */
6882    /*
6883     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6884     * that specifies an instruction that performs "result = r0 op r1".
6885     * This could be an ARM instruction or a function call.  (If the result
6886     * comes back in a register other than r0, you can override "result".)
6887     *
6888     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6889     * vCC (r1).  Useful for integer division and modulus.
6890     *
6891     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6892     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6893     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6894     */
6895    /* binop/lit8 vAA, vBB, #+CC */
6896    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6897    mov     r9, rINST, lsr #8           @ r9<- AA
6898    and     r2, r3, #255                @ r2<- BB
6899    GET_VREG(r0, r2)                    @ r0<- vBB
6900    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6901    .if 1
6902    @cmp     r1, #0                      @ is second operand zero?
6903    beq     common_errDivideByZero
6904    .endif
6905    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6906
6907                               @ optional op; may set condition codes
6908    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6909    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6910    SET_VREG(r1, r9)               @ vAA<- r1
6911    GOTO_OPCODE(ip)                     @ jump to next instruction
6912    /* 10-12 instructions */
6913
6914
6915
6916/* ------------------------------ */
6917    .balign 64
6918.L_OP_AND_INT_LIT8: /* 0xdd */
6919/* File: armv5te/OP_AND_INT_LIT8.S */
6920/* File: armv5te/binopLit8.S */
6921    /*
6922     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6923     * that specifies an instruction that performs "result = r0 op r1".
6924     * This could be an ARM instruction or a function call.  (If the result
6925     * comes back in a register other than r0, you can override "result".)
6926     *
6927     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6928     * vCC (r1).  Useful for integer division and modulus.
6929     *
6930     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6931     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6932     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6933     */
6934    /* binop/lit8 vAA, vBB, #+CC */
6935    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6936    mov     r9, rINST, lsr #8           @ r9<- AA
6937    and     r2, r3, #255                @ r2<- BB
6938    GET_VREG(r0, r2)                    @ r0<- vBB
6939    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6940    .if 0
6941    @cmp     r1, #0                      @ is second operand zero?
6942    beq     common_errDivideByZero
6943    .endif
6944    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6945
6946                               @ optional op; may set condition codes
6947    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6948    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6949    SET_VREG(r0, r9)               @ vAA<- r0
6950    GOTO_OPCODE(ip)                     @ jump to next instruction
6951    /* 10-12 instructions */
6952
6953
6954
6955/* ------------------------------ */
6956    .balign 64
6957.L_OP_OR_INT_LIT8: /* 0xde */
6958/* File: armv5te/OP_OR_INT_LIT8.S */
6959/* File: armv5te/binopLit8.S */
6960    /*
6961     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6962     * that specifies an instruction that performs "result = r0 op r1".
6963     * This could be an ARM instruction or a function call.  (If the result
6964     * comes back in a register other than r0, you can override "result".)
6965     *
6966     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6967     * vCC (r1).  Useful for integer division and modulus.
6968     *
6969     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6970     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6971     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6972     */
6973    /* binop/lit8 vAA, vBB, #+CC */
6974    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6975    mov     r9, rINST, lsr #8           @ r9<- AA
6976    and     r2, r3, #255                @ r2<- BB
6977    GET_VREG(r0, r2)                    @ r0<- vBB
6978    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6979    .if 0
6980    @cmp     r1, #0                      @ is second operand zero?
6981    beq     common_errDivideByZero
6982    .endif
6983    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6984
6985                               @ optional op; may set condition codes
6986    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6987    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6988    SET_VREG(r0, r9)               @ vAA<- r0
6989    GOTO_OPCODE(ip)                     @ jump to next instruction
6990    /* 10-12 instructions */
6991
6992
6993
6994/* ------------------------------ */
6995    .balign 64
6996.L_OP_XOR_INT_LIT8: /* 0xdf */
6997/* File: armv5te/OP_XOR_INT_LIT8.S */
6998/* File: armv5te/binopLit8.S */
6999    /*
7000     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7001     * that specifies an instruction that performs "result = r0 op r1".
7002     * This could be an ARM instruction or a function call.  (If the result
7003     * comes back in a register other than r0, you can override "result".)
7004     *
7005     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7006     * vCC (r1).  Useful for integer division and modulus.
7007     *
7008     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7009     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7010     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7011     */
7012    /* binop/lit8 vAA, vBB, #+CC */
7013    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7014    mov     r9, rINST, lsr #8           @ r9<- AA
7015    and     r2, r3, #255                @ r2<- BB
7016    GET_VREG(r0, r2)                    @ r0<- vBB
7017    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7018    .if 0
7019    @cmp     r1, #0                      @ is second operand zero?
7020    beq     common_errDivideByZero
7021    .endif
7022    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7023
7024                               @ optional op; may set condition codes
7025    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7026    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7027    SET_VREG(r0, r9)               @ vAA<- r0
7028    GOTO_OPCODE(ip)                     @ jump to next instruction
7029    /* 10-12 instructions */
7030
7031
7032
7033/* ------------------------------ */
7034    .balign 64
7035.L_OP_SHL_INT_LIT8: /* 0xe0 */
7036/* File: armv5te/OP_SHL_INT_LIT8.S */
7037/* File: armv5te/binopLit8.S */
7038    /*
7039     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7040     * that specifies an instruction that performs "result = r0 op r1".
7041     * This could be an ARM instruction or a function call.  (If the result
7042     * comes back in a register other than r0, you can override "result".)
7043     *
7044     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7045     * vCC (r1).  Useful for integer division and modulus.
7046     *
7047     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7048     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7049     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7050     */
7051    /* binop/lit8 vAA, vBB, #+CC */
7052    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7053    mov     r9, rINST, lsr #8           @ r9<- AA
7054    and     r2, r3, #255                @ r2<- BB
7055    GET_VREG(r0, r2)                    @ r0<- vBB
7056    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7057    .if 0
7058    @cmp     r1, #0                      @ is second operand zero?
7059    beq     common_errDivideByZero
7060    .endif
7061    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7062
7063    and     r1, r1, #31                           @ optional op; may set condition codes
7064    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7066    SET_VREG(r0, r9)               @ vAA<- r0
7067    GOTO_OPCODE(ip)                     @ jump to next instruction
7068    /* 10-12 instructions */
7069
7070
7071
7072/* ------------------------------ */
7073    .balign 64
7074.L_OP_SHR_INT_LIT8: /* 0xe1 */
7075/* File: armv5te/OP_SHR_INT_LIT8.S */
7076/* File: armv5te/binopLit8.S */
7077    /*
7078     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7079     * that specifies an instruction that performs "result = r0 op r1".
7080     * This could be an ARM instruction or a function call.  (If the result
7081     * comes back in a register other than r0, you can override "result".)
7082     *
7083     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7084     * vCC (r1).  Useful for integer division and modulus.
7085     *
7086     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7087     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7088     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7089     */
7090    /* binop/lit8 vAA, vBB, #+CC */
7091    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7092    mov     r9, rINST, lsr #8           @ r9<- AA
7093    and     r2, r3, #255                @ r2<- BB
7094    GET_VREG(r0, r2)                    @ r0<- vBB
7095    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7096    .if 0
7097    @cmp     r1, #0                      @ is second operand zero?
7098    beq     common_errDivideByZero
7099    .endif
7100    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7101
7102    and     r1, r1, #31                           @ optional op; may set condition codes
7103    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7105    SET_VREG(r0, r9)               @ vAA<- r0
7106    GOTO_OPCODE(ip)                     @ jump to next instruction
7107    /* 10-12 instructions */
7108
7109
7110
7111/* ------------------------------ */
7112    .balign 64
7113.L_OP_USHR_INT_LIT8: /* 0xe2 */
7114/* File: armv5te/OP_USHR_INT_LIT8.S */
7115/* File: armv5te/binopLit8.S */
7116    /*
7117     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7118     * that specifies an instruction that performs "result = r0 op r1".
7119     * This could be an ARM instruction or a function call.  (If the result
7120     * comes back in a register other than r0, you can override "result".)
7121     *
7122     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7123     * vCC (r1).  Useful for integer division and modulus.
7124     *
7125     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7126     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7127     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7128     */
7129    /* binop/lit8 vAA, vBB, #+CC */
7130    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7131    mov     r9, rINST, lsr #8           @ r9<- AA
7132    and     r2, r3, #255                @ r2<- BB
7133    GET_VREG(r0, r2)                    @ r0<- vBB
7134    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7135    .if 0
7136    @cmp     r1, #0                      @ is second operand zero?
7137    beq     common_errDivideByZero
7138    .endif
7139    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7140
7141    and     r1, r1, #31                           @ optional op; may set condition codes
7142    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7144    SET_VREG(r0, r9)               @ vAA<- r0
7145    GOTO_OPCODE(ip)                     @ jump to next instruction
7146    /* 10-12 instructions */
7147
7148
7149
7150/* ------------------------------ */
7151    .balign 64
7152.L_OP_UNUSED_E3: /* 0xe3 */
7153/* File: armv5te/OP_UNUSED_E3.S */
7154/* File: armv5te/unused.S */
7155    bl      common_abort
7156
7157
7158
7159/* ------------------------------ */
7160    .balign 64
7161.L_OP_UNUSED_E4: /* 0xe4 */
7162/* File: armv5te/OP_UNUSED_E4.S */
7163/* File: armv5te/unused.S */
7164    bl      common_abort
7165
7166
7167
7168/* ------------------------------ */
7169    .balign 64
7170.L_OP_UNUSED_E5: /* 0xe5 */
7171/* File: armv5te/OP_UNUSED_E5.S */
7172/* File: armv5te/unused.S */
7173    bl      common_abort
7174
7175
7176
7177/* ------------------------------ */
7178    .balign 64
7179.L_OP_UNUSED_E6: /* 0xe6 */
7180/* File: armv5te/OP_UNUSED_E6.S */
7181/* File: armv5te/unused.S */
7182    bl      common_abort
7183
7184
7185
7186/* ------------------------------ */
7187    .balign 64
7188.L_OP_UNUSED_E7: /* 0xe7 */
7189/* File: armv5te/OP_UNUSED_E7.S */
7190/* File: armv5te/unused.S */
7191    bl      common_abort
7192
7193
7194
7195/* ------------------------------ */
7196    .balign 64
7197.L_OP_UNUSED_E8: /* 0xe8 */
7198/* File: armv5te/OP_UNUSED_E8.S */
7199/* File: armv5te/unused.S */
7200    bl      common_abort
7201
7202
7203
7204/* ------------------------------ */
7205    .balign 64
7206.L_OP_UNUSED_E9: /* 0xe9 */
7207/* File: armv5te/OP_UNUSED_E9.S */
7208/* File: armv5te/unused.S */
7209    bl      common_abort
7210
7211
7212
7213/* ------------------------------ */
7214    .balign 64
7215.L_OP_UNUSED_EA: /* 0xea */
7216/* File: armv5te/OP_UNUSED_EA.S */
7217/* File: armv5te/unused.S */
7218    bl      common_abort
7219
7220
7221
7222/* ------------------------------ */
7223    .balign 64
7224.L_OP_UNUSED_EB: /* 0xeb */
7225/* File: armv5te/OP_UNUSED_EB.S */
7226/* File: armv5te/unused.S */
7227    bl      common_abort
7228
7229
7230
7231/* ------------------------------ */
7232    .balign 64
7233.L_OP_BREAKPOINT: /* 0xec */
7234/* File: armv5te/OP_BREAKPOINT.S */
7235/* File: armv5te/unused.S */
7236    bl      common_abort
7237
7238
7239
7240/* ------------------------------ */
7241    .balign 64
7242.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7243/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7244    /*
7245     * Handle a throw-verification-error instruction.  This throws an
7246     * exception for an error discovered during verification.  The
7247     * exception is indicated by AA, with some detail provided by BBBB.
7248     */
7249    /* op AA, ref@BBBB */
7250    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7251    FETCH(r2, 1)                        @ r2<- BBBB
7252    EXPORT_PC()                         @ export the PC
7253    mov     r1, rINST, lsr #8           @ r1<- AA
7254    bl      dvmThrowVerificationError   @ always throws
7255    b       common_exceptionThrown      @ handle exception
7256
7257
7258/* ------------------------------ */
7259    .balign 64
7260.L_OP_EXECUTE_INLINE: /* 0xee */
7261/* File: armv5te/OP_EXECUTE_INLINE.S */
7262    /*
7263     * Execute a "native inline" instruction.
7264     *
7265     * We need to call an InlineOp4Func:
7266     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7267     *
7268     * The first four args are in r0-r3, pointer to return value storage
7269     * is on the stack.  The function's return value is a flag that tells
7270     * us if an exception was thrown.
7271     */
7272    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7273    FETCH(r10, 1)                       @ r10<- BBBB
7274    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7275    EXPORT_PC()                         @ can throw
7276    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7277    mov     r0, rINST, lsr #12          @ r0<- B
7278    str     r1, [sp]                    @ push &glue->retval
7279    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7280    add     sp, sp, #8                  @ pop stack
7281    cmp     r0, #0                      @ test boolean result of inline
7282    beq     common_exceptionThrown      @ returned false, handle exception
7283    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7285    GOTO_OPCODE(ip)                     @ jump to next instruction
7286
7287/* ------------------------------ */
7288    .balign 64
7289.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7290/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7291    /*
7292     * Execute a "native inline" instruction, using "/range" semantics.
7293     * Same idea as execute-inline, but we get the args differently.
7294     *
7295     * We need to call an InlineOp4Func:
7296     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7297     *
7298     * The first four args are in r0-r3, pointer to return value storage
7299     * is on the stack.  The function's return value is a flag that tells
7300     * us if an exception was thrown.
7301     */
7302    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7303    FETCH(r10, 1)                       @ r10<- BBBB
7304    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7305    EXPORT_PC()                         @ can throw
7306    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7307    mov     r0, rINST, lsr #8           @ r0<- AA
7308    str     r1, [sp]                    @ push &glue->retval
7309    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7310    add     sp, sp, #8                  @ pop stack
7311    cmp     r0, #0                      @ test boolean result of inline
7312    beq     common_exceptionThrown      @ returned false, handle exception
7313    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7314    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7315    GOTO_OPCODE(ip)                     @ jump to next instruction
7316
7317/* ------------------------------ */
7318    .balign 64
7319.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7320/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7321    /*
7322     * invoke-direct-empty is a no-op in a "standard" interpreter.
7323     */
7324    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7325    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7326    GOTO_OPCODE(ip)                     @ execute it
7327
7328/* ------------------------------ */
7329    .balign 64
7330.L_OP_UNUSED_F1: /* 0xf1 */
7331/* File: armv5te/OP_UNUSED_F1.S */
7332/* File: armv5te/unused.S */
7333    bl      common_abort
7334
7335
7336
7337/* ------------------------------ */
7338    .balign 64
7339.L_OP_IGET_QUICK: /* 0xf2 */
7340/* File: armv6t2/OP_IGET_QUICK.S */
7341    /* For: iget-quick, iget-object-quick */
7342    /* op vA, vB, offset@CCCC */
7343    mov     r2, rINST, lsr #12          @ r2<- B
7344    FETCH(r1, 1)                        @ r1<- field byte offset
7345    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7346    ubfx    r2, rINST, #8, #4           @ r2<- A
7347    cmp     r3, #0                      @ check object for null
7348    beq     common_errNullObject        @ object was null
7349    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7350    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7351    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7352    SET_VREG(r0, r2)                    @ fp[A]<- r0
7353    GOTO_OPCODE(ip)                     @ jump to next instruction
7354
7355
7356/* ------------------------------ */
7357    .balign 64
7358.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7359/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7360    /* iget-wide-quick vA, vB, offset@CCCC */
7361    mov     r2, rINST, lsr #12          @ r2<- B
7362    FETCH(r1, 1)                        @ r1<- field byte offset
7363    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7364    ubfx    r2, rINST, #8, #4           @ r2<- A
7365    cmp     r3, #0                      @ check object for null
7366    beq     common_errNullObject        @ object was null
7367    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
7368    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7369    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7371    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7372    GOTO_OPCODE(ip)                     @ jump to next instruction
7373
7374
7375/* ------------------------------ */
7376    .balign 64
7377.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7378/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7379/* File: armv5te/OP_IGET_QUICK.S */
7380    /* For: iget-quick, iget-object-quick */
7381    /* op vA, vB, offset@CCCC */
7382    mov     r2, rINST, lsr #12          @ r2<- B
7383    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7384    FETCH(r1, 1)                        @ r1<- field byte offset
7385    cmp     r3, #0                      @ check object for null
7386    mov     r2, rINST, lsr #8           @ r2<- A(+)
7387    beq     common_errNullObject        @ object was null
7388    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7389    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7390    and     r2, r2, #15
7391    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7392    SET_VREG(r0, r2)                    @ fp[A]<- r0
7393    GOTO_OPCODE(ip)                     @ jump to next instruction
7394
7395
7396
7397/* ------------------------------ */
7398    .balign 64
7399.L_OP_IPUT_QUICK: /* 0xf5 */
7400/* File: armv6t2/OP_IPUT_QUICK.S */
7401    /* For: iput-quick, iput-object-quick */
7402    /* op vA, vB, offset@CCCC */
7403    mov     r2, rINST, lsr #12          @ r2<- B
7404    FETCH(r1, 1)                        @ r1<- field byte offset
7405    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7406    ubfx    r2, rINST, #8, #4           @ r2<- A
7407    cmp     r3, #0                      @ check object for null
7408    beq     common_errNullObject        @ object was null
7409    GET_VREG(r0, r2)                    @ r0<- fp[A]
7410    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7411    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7413    GOTO_OPCODE(ip)                     @ jump to next instruction
7414
7415
7416/* ------------------------------ */
7417    .balign 64
7418.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7419/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7420    /* iput-wide-quick vA, vB, offset@CCCC */
7421    mov     r1, rINST, lsr #12          @ r1<- B
7422    ubfx    r0, rINST, #8, #4           @ r0<- A
7423    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7424    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7425    cmp     r2, #0                      @ check object for null
7426    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7427    beq     common_errNullObject        @ object was null
7428    FETCH(r3, 1)                        @ r3<- field byte offset
7429    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7430    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7432    GOTO_OPCODE(ip)                     @ jump to next instruction
7433
7434
7435/* ------------------------------ */
7436    .balign 64
7437.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7438/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7439/* File: armv5te/OP_IPUT_QUICK.S */
7440    /* For: iput-quick, iput-object-quick */
7441    /* op vA, vB, offset@CCCC */
7442    mov     r2, rINST, lsr #12          @ r2<- B
7443    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7444    FETCH(r1, 1)                        @ r1<- field byte offset
7445    cmp     r3, #0                      @ check object for null
7446    mov     r2, rINST, lsr #8           @ r2<- A(+)
7447    beq     common_errNullObject        @ object was null
7448    and     r2, r2, #15
7449    GET_VREG(r0, r2)                    @ r0<- fp[A]
7450    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7451    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7452    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7453    GOTO_OPCODE(ip)                     @ jump to next instruction
7454
7455
7456
7457/* ------------------------------ */
7458    .balign 64
7459.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7460/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7461    /*
7462     * Handle an optimized virtual method call.
7463     *
7464     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7465     */
7466    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7467    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7468    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7469    FETCH(r1, 1)                        @ r1<- BBBB
7470    .if     (!0)
7471    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7472    .endif
7473    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7474    cmp     r2, #0                      @ is "this" null?
7475    beq     common_errNullObject        @ null "this", throw exception
7476    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7477    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7478    EXPORT_PC()                         @ invoke must export
7479    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7480    bl      common_invokeMethodNoRange @ continue on
7481
7482/* ------------------------------ */
7483    .balign 64
7484.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7485/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7486/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7487    /*
7488     * Handle an optimized virtual method call.
7489     *
7490     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7491     */
7492    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7493    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7494    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7495    FETCH(r1, 1)                        @ r1<- BBBB
7496    .if     (!1)
7497    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7498    .endif
7499    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7500    cmp     r2, #0                      @ is "this" null?
7501    beq     common_errNullObject        @ null "this", throw exception
7502    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7503    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7504    EXPORT_PC()                         @ invoke must export
7505    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7506    bl      common_invokeMethodRange @ continue on
7507
7508
7509/* ------------------------------ */
7510    .balign 64
7511.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7512/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7513    /*
7514     * Handle an optimized "super" method call.
7515     *
7516     * for: [opt] invoke-super-quick, invoke-super-quick/range
7517     */
7518    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7519    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7520    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7521    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7522    .if     (!0)
7523    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7524    .endif
7525    FETCH(r1, 1)                        @ r1<- BBBB
7526    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7527    EXPORT_PC()                         @ must export for invoke
7528    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7529    GET_VREG(r3, r10)                   @ r3<- "this"
7530    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7531    cmp     r3, #0                      @ null "this" ref?
7532    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7533    beq     common_errNullObject        @ "this" is null, throw exception
7534    bl      common_invokeMethodNoRange @ continue on
7535
7536
7537/* ------------------------------ */
7538    .balign 64
7539.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7540/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7541/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7542    /*
7543     * Handle an optimized "super" method call.
7544     *
7545     * for: [opt] invoke-super-quick, invoke-super-quick/range
7546     */
7547    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7548    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7549    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7550    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7551    .if     (!1)
7552    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7553    .endif
7554    FETCH(r1, 1)                        @ r1<- BBBB
7555    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7556    EXPORT_PC()                         @ must export for invoke
7557    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7558    GET_VREG(r3, r10)                   @ r3<- "this"
7559    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7560    cmp     r3, #0                      @ null "this" ref?
7561    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7562    beq     common_errNullObject        @ "this" is null, throw exception
7563    bl      common_invokeMethodRange @ continue on
7564
7565
7566
7567/* ------------------------------ */
7568    .balign 64
7569.L_OP_UNUSED_FC: /* 0xfc */
7570/* File: armv5te/OP_UNUSED_FC.S */
7571/* File: armv5te/unused.S */
7572    bl      common_abort
7573
7574
7575
7576/* ------------------------------ */
7577    .balign 64
7578.L_OP_UNUSED_FD: /* 0xfd */
7579/* File: armv5te/OP_UNUSED_FD.S */
7580/* File: armv5te/unused.S */
7581    bl      common_abort
7582
7583
7584
7585/* ------------------------------ */
7586    .balign 64
7587.L_OP_UNUSED_FE: /* 0xfe */
7588/* File: armv5te/OP_UNUSED_FE.S */
7589/* File: armv5te/unused.S */
7590    bl      common_abort
7591
7592
7593
7594/* ------------------------------ */
7595    .balign 64
7596.L_OP_UNUSED_FF: /* 0xff */
7597/* File: armv5te/OP_UNUSED_FF.S */
7598/* File: armv5te/unused.S */
7599    bl      common_abort
7600
7601
7602
7603
7604    .balign 64
7605    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7606    .global dvmAsmInstructionEnd
7607dvmAsmInstructionEnd:
7608
7609/*
7610 * ===========================================================================
7611 *  Sister implementations
7612 * ===========================================================================
7613 */
7614    .global dvmAsmSisterStart
7615    .type   dvmAsmSisterStart, %function
7616    .text
7617    .balign 4
7618dvmAsmSisterStart:
7619
7620/* continuation for OP_CONST_STRING */
7621
7622    /*
7623     * Continuation if the String has not yet been resolved.
7624     *  r1: BBBB (String ref)
7625     *  r9: target register
7626     */
7627.LOP_CONST_STRING_resolve:
7628    EXPORT_PC()
7629    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7630    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7631    bl      dvmResolveString            @ r0<- String reference
7632    cmp     r0, #0                      @ failed?
7633    beq     common_exceptionThrown      @ yup, handle the exception
7634    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7635    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7636    SET_VREG(r0, r9)                    @ vAA<- r0
7637    GOTO_OPCODE(ip)                     @ jump to next instruction
7638
7639
7640/* continuation for OP_CONST_STRING_JUMBO */
7641
7642    /*
7643     * Continuation if the String has not yet been resolved.
7644     *  r1: BBBBBBBB (String ref)
7645     *  r9: target register
7646     */
7647.LOP_CONST_STRING_JUMBO_resolve:
7648    EXPORT_PC()
7649    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7650    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7651    bl      dvmResolveString            @ r0<- String reference
7652    cmp     r0, #0                      @ failed?
7653    beq     common_exceptionThrown      @ yup, handle the exception
7654    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7655    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7656    SET_VREG(r0, r9)                    @ vAA<- r0
7657    GOTO_OPCODE(ip)                     @ jump to next instruction
7658
7659
7660/* continuation for OP_CONST_CLASS */
7661
7662    /*
7663     * Continuation if the Class has not yet been resolved.
7664     *  r1: BBBB (Class ref)
7665     *  r9: target register
7666     */
7667.LOP_CONST_CLASS_resolve:
7668    EXPORT_PC()
7669    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7670    mov     r2, #1                      @ r2<- true
7671    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7672    bl      dvmResolveClass             @ r0<- Class reference
7673    cmp     r0, #0                      @ failed?
7674    beq     common_exceptionThrown      @ yup, handle the exception
7675    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7677    SET_VREG(r0, r9)                    @ vAA<- r0
7678    GOTO_OPCODE(ip)                     @ jump to next instruction
7679
7680
7681/* continuation for OP_CHECK_CAST */
7682
7683    /*
7684     * Trivial test failed, need to perform full check.  This is common.
7685     *  r0 holds obj->clazz
7686     *  r1 holds class resolved from BBBB
7687     *  r9 holds object
7688     */
7689.LOP_CHECK_CAST_fullcheck:
7690    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7691    cmp     r0, #0                      @ failed?
7692    bne     .LOP_CHECK_CAST_okay            @ no, success
7693
7694    @ A cast has failed.  We need to throw a ClassCastException with the
7695    @ class of the object that failed to be cast.
7696    EXPORT_PC()                         @ about to throw
7697    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7698    ldr     r0, .LstrClassCastExceptionPtr
7699    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7700    bl      dvmThrowExceptionWithClassMessage
7701    b       common_exceptionThrown
7702
7703    /*
7704     * Resolution required.  This is the least-likely path.
7705     *
7706     *  r2 holds BBBB
7707     *  r9 holds object
7708     */
7709.LOP_CHECK_CAST_resolve:
7710    EXPORT_PC()                         @ resolve() could throw
7711    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7712    mov     r1, r2                      @ r1<- BBBB
7713    mov     r2, #0                      @ r2<- false
7714    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7715    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7716    cmp     r0, #0                      @ got null?
7717    beq     common_exceptionThrown      @ yes, handle exception
7718    mov     r1, r0                      @ r1<- class resolved from BBB
7719    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7720    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7721
7722.LstrClassCastExceptionPtr:
7723    .word   .LstrClassCastException
7724
7725
7726/* continuation for OP_INSTANCE_OF */
7727
7728    /*
7729     * Trivial test failed, need to perform full check.  This is common.
7730     *  r0 holds obj->clazz
7731     *  r1 holds class resolved from BBBB
7732     *  r9 holds A
7733     */
7734.LOP_INSTANCE_OF_fullcheck:
7735    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7736    @ fall through to OP_INSTANCE_OF_store
7737
7738    /*
7739     * r0 holds boolean result
7740     * r9 holds A
7741     */
7742.LOP_INSTANCE_OF_store:
7743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7744    SET_VREG(r0, r9)                    @ vA<- r0
7745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7746    GOTO_OPCODE(ip)                     @ jump to next instruction
7747
7748    /*
7749     * Trivial test succeeded, save and bail.
7750     *  r9 holds A
7751     */
7752.LOP_INSTANCE_OF_trivial:
7753    mov     r0, #1                      @ indicate success
7754    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7755    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7756    SET_VREG(r0, r9)                    @ vA<- r0
7757    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7758    GOTO_OPCODE(ip)                     @ jump to next instruction
7759
7760    /*
7761     * Resolution required.  This is the least-likely path.
7762     *
7763     *  r3 holds BBBB
7764     *  r9 holds A
7765     */
7766.LOP_INSTANCE_OF_resolve:
7767    EXPORT_PC()                         @ resolve() could throw
7768    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7769    mov     r1, r3                      @ r1<- BBBB
7770    mov     r2, #1                      @ r2<- true
7771    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7772    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7773    cmp     r0, #0                      @ got null?
7774    beq     common_exceptionThrown      @ yes, handle exception
7775    mov     r1, r0                      @ r1<- class resolved from BBB
7776    mov     r3, rINST, lsr #12          @ r3<- B
7777    GET_VREG(r0, r3)                    @ r0<- vB (object)
7778    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7779    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7780
7781
7782/* continuation for OP_NEW_INSTANCE */
7783
7784    .balign 32                          @ minimize cache lines
7785.LOP_NEW_INSTANCE_finish: @ r0=new object
7786    mov     r3, rINST, lsr #8           @ r3<- AA
7787    cmp     r0, #0                      @ failed?
7788    beq     common_exceptionThrown      @ yes, handle the exception
7789    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7791    SET_VREG(r0, r3)                    @ vAA<- r0
7792    GOTO_OPCODE(ip)                     @ jump to next instruction
7793
7794    /*
7795     * Class initialization required.
7796     *
7797     *  r0 holds class object
7798     */
7799.LOP_NEW_INSTANCE_needinit:
7800    mov     r9, r0                      @ save r0
7801    bl      dvmInitClass                @ initialize class
7802    cmp     r0, #0                      @ check boolean result
7803    mov     r0, r9                      @ restore r0
7804    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7805    b       common_exceptionThrown      @ failed, deal with init exception
7806
7807    /*
7808     * Resolution required.  This is the least-likely path.
7809     *
7810     *  r1 holds BBBB
7811     */
7812.LOP_NEW_INSTANCE_resolve:
7813    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7814    mov     r2, #0                      @ r2<- false
7815    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7816    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7817    cmp     r0, #0                      @ got null?
7818    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7819    b       common_exceptionThrown      @ yes, handle exception
7820
7821.LstrInstantiationErrorPtr:
7822    .word   .LstrInstantiationError
7823
7824
7825/* continuation for OP_NEW_ARRAY */
7826
7827
7828    /*
7829     * Resolve class.  (This is an uncommon case.)
7830     *
7831     *  r1 holds array length
7832     *  r2 holds class ref CCCC
7833     */
7834.LOP_NEW_ARRAY_resolve:
7835    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7836    mov     r9, r1                      @ r9<- length (save)
7837    mov     r1, r2                      @ r1<- CCCC
7838    mov     r2, #0                      @ r2<- false
7839    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7840    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7841    cmp     r0, #0                      @ got null?
7842    mov     r1, r9                      @ r1<- length (restore)
7843    beq     common_exceptionThrown      @ yes, handle exception
7844    @ fall through to OP_NEW_ARRAY_finish
7845
7846    /*
7847     * Finish allocation.
7848     *
7849     *  r0 holds class
7850     *  r1 holds array length
7851     */
7852.LOP_NEW_ARRAY_finish:
7853    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7854    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7855    cmp     r0, #0                      @ failed?
7856    mov     r2, rINST, lsr #8           @ r2<- A+
7857    beq     common_exceptionThrown      @ yes, handle the exception
7858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7859    and     r2, r2, #15                 @ r2<- A
7860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7861    SET_VREG(r0, r2)                    @ vA<- r0
7862    GOTO_OPCODE(ip)                     @ jump to next instruction
7863
7864
7865/* continuation for OP_FILLED_NEW_ARRAY */
7866
7867    /*
7868     * On entry:
7869     *  r0 holds array class
7870     *  r10 holds AA or BA
7871     */
7872.LOP_FILLED_NEW_ARRAY_continue:
7873    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7874    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7875    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7876    .if     0
7877    mov     r1, r10                     @ r1<- AA (length)
7878    .else
7879    mov     r1, r10, lsr #4             @ r1<- B (length)
7880    .endif
7881    cmp     r3, #'I'                    @ array of ints?
7882    cmpne   r3, #'L'                    @ array of objects?
7883    cmpne   r3, #'['                    @ array of arrays?
7884    mov     r9, r1                      @ save length in r9
7885    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7886    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7887    cmp     r0, #0                      @ null return?
7888    beq     common_exceptionThrown      @ alloc failed, handle exception
7889
7890    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7891    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7892    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7893    subs    r9, r9, #1                  @ length--, check for neg
7894    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7895    bmi     2f                          @ was zero, bail
7896
7897    @ copy values from registers into the array
7898    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7899    .if     0
7900    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79011:  ldr     r3, [r2], #4                @ r3<- *r2++
7902    subs    r9, r9, #1                  @ count--
7903    str     r3, [r0], #4                @ *contents++ = vX
7904    bpl     1b
7905    @ continue at 2
7906    .else
7907    cmp     r9, #4                      @ length was initially 5?
7908    and     r2, r10, #15                @ r2<- A
7909    bne     1f                          @ <= 4 args, branch
7910    GET_VREG(r3, r2)                    @ r3<- vA
7911    sub     r9, r9, #1                  @ count--
7912    str     r3, [r0, #16]               @ contents[4] = vA
79131:  and     r2, r1, #15                 @ r2<- F/E/D/C
7914    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7915    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7916    subs    r9, r9, #1                  @ count--
7917    str     r3, [r0], #4                @ *contents++ = vX
7918    bpl     1b
7919    @ continue at 2
7920    .endif
7921
79222:
7923    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7924    GOTO_OPCODE(ip)                     @ execute it
7925
7926    /*
7927     * Throw an exception indicating that we have not implemented this
7928     * mode of filled-new-array.
7929     */
7930.LOP_FILLED_NEW_ARRAY_notimpl:
7931    ldr     r0, .L_strInternalError
7932    ldr     r1, .L_strFilledNewArrayNotImpl
7933    bl      dvmThrowException
7934    b       common_exceptionThrown
7935
7936    .if     (!0)                 @ define in one or the other, not both
7937.L_strFilledNewArrayNotImpl:
7938    .word   .LstrFilledNewArrayNotImpl
7939.L_strInternalError:
7940    .word   .LstrInternalError
7941    .endif
7942
7943
7944/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
7945
7946    /*
7947     * On entry:
7948     *  r0 holds array class
7949     *  r10 holds AA or BA
7950     */
7951.LOP_FILLED_NEW_ARRAY_RANGE_continue:
7952    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7953    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7954    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
7955    .if     1
7956    mov     r1, r10                     @ r1<- AA (length)
7957    .else
7958    mov     r1, r10, lsr #4             @ r1<- B (length)
7959    .endif
7960    cmp     r3, #'I'                    @ array of ints?
7961    cmpne   r3, #'L'                    @ array of objects?
7962    cmpne   r3, #'['                    @ array of arrays?
7963    mov     r9, r1                      @ save length in r9
7964    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
7965    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7966    cmp     r0, #0                      @ null return?
7967    beq     common_exceptionThrown      @ alloc failed, handle exception
7968
7969    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7970    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
7971    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7972    subs    r9, r9, #1                  @ length--, check for neg
7973    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7974    bmi     2f                          @ was zero, bail
7975
7976    @ copy values from registers into the array
7977    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7978    .if     1
7979    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79801:  ldr     r3, [r2], #4                @ r3<- *r2++
7981    subs    r9, r9, #1                  @ count--
7982    str     r3, [r0], #4                @ *contents++ = vX
7983    bpl     1b
7984    @ continue at 2
7985    .else
7986    cmp     r9, #4                      @ length was initially 5?
7987    and     r2, r10, #15                @ r2<- A
7988    bne     1f                          @ <= 4 args, branch
7989    GET_VREG(r3, r2)                    @ r3<- vA
7990    sub     r9, r9, #1                  @ count--
7991    str     r3, [r0, #16]               @ contents[4] = vA
79921:  and     r2, r1, #15                 @ r2<- F/E/D/C
7993    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
7994    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
7995    subs    r9, r9, #1                  @ count--
7996    str     r3, [r0], #4                @ *contents++ = vX
7997    bpl     1b
7998    @ continue at 2
7999    .endif
8000
80012:
8002    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8003    GOTO_OPCODE(ip)                     @ execute it
8004
8005    /*
8006     * Throw an exception indicating that we have not implemented this
8007     * mode of filled-new-array.
8008     */
8009.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8010    ldr     r0, .L_strInternalError
8011    ldr     r1, .L_strFilledNewArrayNotImpl
8012    bl      dvmThrowException
8013    b       common_exceptionThrown
8014
8015    .if     (!1)                 @ define in one or the other, not both
8016.L_strFilledNewArrayNotImpl:
8017    .word   .LstrFilledNewArrayNotImpl
8018.L_strInternalError:
8019    .word   .LstrInternalError
8020    .endif
8021
8022
8023/* continuation for OP_CMPL_FLOAT */
8024.LOP_CMPL_FLOAT_finish:
8025    SET_VREG(r0, r9)                    @ vAA<- r0
8026    GOTO_OPCODE(ip)                     @ jump to next instruction
8027
8028
8029/* continuation for OP_CMPG_FLOAT */
8030.LOP_CMPG_FLOAT_finish:
8031    SET_VREG(r0, r9)                    @ vAA<- r0
8032    GOTO_OPCODE(ip)                     @ jump to next instruction
8033
8034
8035/* continuation for OP_CMPL_DOUBLE */
8036.LOP_CMPL_DOUBLE_finish:
8037    SET_VREG(r0, r9)                    @ vAA<- r0
8038    GOTO_OPCODE(ip)                     @ jump to next instruction
8039
8040
8041/* continuation for OP_CMPG_DOUBLE */
8042.LOP_CMPG_DOUBLE_finish:
8043    SET_VREG(r0, r9)                    @ vAA<- r0
8044    GOTO_OPCODE(ip)                     @ jump to next instruction
8045
8046
8047/* continuation for OP_CMP_LONG */
8048
8049.LOP_CMP_LONG_less:
8050    mvn     r1, #0                      @ r1<- -1
8051    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8052    @ instead, we just replicate the tail end.
8053    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8054    SET_VREG(r1, r9)                    @ vAA<- r1
8055    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8056    GOTO_OPCODE(ip)                     @ jump to next instruction
8057
8058.LOP_CMP_LONG_greater:
8059    mov     r1, #1                      @ r1<- 1
8060    @ fall through to _finish
8061
8062.LOP_CMP_LONG_finish:
8063    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8064    SET_VREG(r1, r9)                    @ vAA<- r1
8065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8066    GOTO_OPCODE(ip)                     @ jump to next instruction
8067
8068
8069/* continuation for OP_AGET_WIDE */
8070
8071.LOP_AGET_WIDE_finish:
8072    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8073    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8074    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8075    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8076    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8077    GOTO_OPCODE(ip)                     @ jump to next instruction
8078
8079
8080/* continuation for OP_APUT_WIDE */
8081
8082.LOP_APUT_WIDE_finish:
8083    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8084    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8085    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8086    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8087    GOTO_OPCODE(ip)                     @ jump to next instruction
8088
8089
8090/* continuation for OP_APUT_OBJECT */
8091    /*
8092     * On entry:
8093     *  r1 = vBB (arrayObj)
8094     *  r9 = vAA (obj)
8095     *  r10 = offset into array (vBB + vCC * width)
8096     */
8097.LOP_APUT_OBJECT_finish:
8098    cmp     r9, #0                      @ storing null reference?
8099    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8100    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8101    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8102    bl      dvmCanPutArrayElement       @ test object type vs. array type
8103    cmp     r0, #0                      @ okay?
8104    beq     common_errArrayStore        @ no
8105.LOP_APUT_OBJECT_skip_check:
8106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8107    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8108    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8109    GOTO_OPCODE(ip)                     @ jump to next instruction
8110
8111
8112/* continuation for OP_IGET */
8113
8114    /*
8115     * Currently:
8116     *  r0 holds resolved field
8117     *  r9 holds object
8118     */
8119.LOP_IGET_finish:
8120    @bl      common_squeak0
8121    cmp     r9, #0                      @ check object for null
8122    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8123    beq     common_errNullObject        @ object was null
8124    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8125    ubfx    r2, rINST, #8, #4           @ r2<- A
8126    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8127    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8128    SET_VREG(r0, r2)                    @ fp[A]<- r0
8129    GOTO_OPCODE(ip)                     @ jump to next instruction
8130
8131
8132/* continuation for OP_IGET_WIDE */
8133
8134    /*
8135     * Currently:
8136     *  r0 holds resolved field
8137     *  r9 holds object
8138     */
8139.LOP_IGET_WIDE_finish:
8140    cmp     r9, #0                      @ check object for null
8141    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8142    beq     common_errNullObject        @ object was null
8143    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8144    ubfx    r2, rINST, #8, #4           @ r2<- A
8145    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8146    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8148    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8149    GOTO_OPCODE(ip)                     @ jump to next instruction
8150
8151
8152/* continuation for OP_IGET_OBJECT */
8153
8154    /*
8155     * Currently:
8156     *  r0 holds resolved field
8157     *  r9 holds object
8158     */
8159.LOP_IGET_OBJECT_finish:
8160    @bl      common_squeak0
8161    cmp     r9, #0                      @ check object for null
8162    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8163    beq     common_errNullObject        @ object was null
8164    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8165    mov     r2, rINST, lsr #8           @ r2<- A+
8166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8167    and     r2, r2, #15                 @ r2<- A
8168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8169    SET_VREG(r0, r2)                    @ fp[A]<- r0
8170    GOTO_OPCODE(ip)                     @ jump to next instruction
8171
8172
8173/* continuation for OP_IGET_BOOLEAN */
8174
8175    /*
8176     * Currently:
8177     *  r0 holds resolved field
8178     *  r9 holds object
8179     */
8180.LOP_IGET_BOOLEAN_finish:
8181    @bl      common_squeak1
8182    cmp     r9, #0                      @ check object for null
8183    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8184    beq     common_errNullObject        @ object was null
8185    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8186    mov     r2, rINST, lsr #8           @ r2<- A+
8187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8188    and     r2, r2, #15                 @ r2<- A
8189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8190    SET_VREG(r0, r2)                    @ fp[A]<- r0
8191    GOTO_OPCODE(ip)                     @ jump to next instruction
8192
8193
8194/* continuation for OP_IGET_BYTE */
8195
8196    /*
8197     * Currently:
8198     *  r0 holds resolved field
8199     *  r9 holds object
8200     */
8201.LOP_IGET_BYTE_finish:
8202    @bl      common_squeak2
8203    cmp     r9, #0                      @ check object for null
8204    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8205    beq     common_errNullObject        @ object was null
8206    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8207    mov     r2, rINST, lsr #8           @ r2<- A+
8208    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8209    and     r2, r2, #15                 @ r2<- A
8210    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8211    SET_VREG(r0, r2)                    @ fp[A]<- r0
8212    GOTO_OPCODE(ip)                     @ jump to next instruction
8213
8214
8215/* continuation for OP_IGET_CHAR */
8216
8217    /*
8218     * Currently:
8219     *  r0 holds resolved field
8220     *  r9 holds object
8221     */
8222.LOP_IGET_CHAR_finish:
8223    @bl      common_squeak3
8224    cmp     r9, #0                      @ check object for null
8225    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8226    beq     common_errNullObject        @ object was null
8227    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8228    mov     r2, rINST, lsr #8           @ r2<- A+
8229    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8230    and     r2, r2, #15                 @ r2<- A
8231    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8232    SET_VREG(r0, r2)                    @ fp[A]<- r0
8233    GOTO_OPCODE(ip)                     @ jump to next instruction
8234
8235
8236/* continuation for OP_IGET_SHORT */
8237
8238    /*
8239     * Currently:
8240     *  r0 holds resolved field
8241     *  r9 holds object
8242     */
8243.LOP_IGET_SHORT_finish:
8244    @bl      common_squeak4
8245    cmp     r9, #0                      @ check object for null
8246    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8247    beq     common_errNullObject        @ object was null
8248    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8249    mov     r2, rINST, lsr #8           @ r2<- A+
8250    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8251    and     r2, r2, #15                 @ r2<- A
8252    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8253    SET_VREG(r0, r2)                    @ fp[A]<- r0
8254    GOTO_OPCODE(ip)                     @ jump to next instruction
8255
8256
8257/* continuation for OP_IPUT */
8258
8259    /*
8260     * Currently:
8261     *  r0 holds resolved field
8262     *  r9 holds object
8263     */
8264.LOP_IPUT_finish:
8265    @bl      common_squeak0
8266    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8267    ubfx    r1, rINST, #8, #4           @ r1<- A
8268    cmp     r9, #0                      @ check object for null
8269    GET_VREG(r0, r1)                    @ r0<- fp[A]
8270    beq     common_errNullObject        @ object was null
8271    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8272    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8273    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8274    GOTO_OPCODE(ip)                     @ jump to next instruction
8275
8276
8277/* continuation for OP_IPUT_WIDE */
8278
8279    /*
8280     * Currently:
8281     *  r0 holds resolved field
8282     *  r9 holds object
8283     */
8284.LOP_IPUT_WIDE_finish:
8285    ubfx    r2, rINST, #8, #4           @ r2<- A
8286    cmp     r9, #0                      @ check object for null
8287    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8288    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8289    beq     common_errNullObject        @ object was null
8290    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8291    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8292    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8293    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8294    GOTO_OPCODE(ip)                     @ jump to next instruction
8295
8296
8297/* continuation for OP_IPUT_OBJECT */
8298
8299    /*
8300     * Currently:
8301     *  r0 holds resolved field
8302     *  r9 holds object
8303     */
8304.LOP_IPUT_OBJECT_finish:
8305    @bl      common_squeak0
8306    mov     r1, rINST, lsr #8           @ r1<- A+
8307    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8308    and     r1, r1, #15                 @ r1<- A
8309    cmp     r9, #0                      @ check object for null
8310    GET_VREG(r0, r1)                    @ r0<- fp[A]
8311    beq     common_errNullObject        @ object was null
8312    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8313    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8314    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8315    GOTO_OPCODE(ip)                     @ jump to next instruction
8316
8317
8318/* continuation for OP_IPUT_BOOLEAN */
8319
8320    /*
8321     * Currently:
8322     *  r0 holds resolved field
8323     *  r9 holds object
8324     */
8325.LOP_IPUT_BOOLEAN_finish:
8326    @bl      common_squeak1
8327    mov     r1, rINST, lsr #8           @ r1<- A+
8328    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8329    and     r1, r1, #15                 @ r1<- A
8330    cmp     r9, #0                      @ check object for null
8331    GET_VREG(r0, r1)                    @ r0<- fp[A]
8332    beq     common_errNullObject        @ object was null
8333    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8334    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8335    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8336    GOTO_OPCODE(ip)                     @ jump to next instruction
8337
8338
8339/* continuation for OP_IPUT_BYTE */
8340
8341    /*
8342     * Currently:
8343     *  r0 holds resolved field
8344     *  r9 holds object
8345     */
8346.LOP_IPUT_BYTE_finish:
8347    @bl      common_squeak2
8348    mov     r1, rINST, lsr #8           @ r1<- A+
8349    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8350    and     r1, r1, #15                 @ r1<- A
8351    cmp     r9, #0                      @ check object for null
8352    GET_VREG(r0, r1)                    @ r0<- fp[A]
8353    beq     common_errNullObject        @ object was null
8354    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8355    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8356    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8357    GOTO_OPCODE(ip)                     @ jump to next instruction
8358
8359
8360/* continuation for OP_IPUT_CHAR */
8361
8362    /*
8363     * Currently:
8364     *  r0 holds resolved field
8365     *  r9 holds object
8366     */
8367.LOP_IPUT_CHAR_finish:
8368    @bl      common_squeak3
8369    mov     r1, rINST, lsr #8           @ r1<- A+
8370    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8371    and     r1, r1, #15                 @ r1<- A
8372    cmp     r9, #0                      @ check object for null
8373    GET_VREG(r0, r1)                    @ r0<- fp[A]
8374    beq     common_errNullObject        @ object was null
8375    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8376    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8377    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8378    GOTO_OPCODE(ip)                     @ jump to next instruction
8379
8380
8381/* continuation for OP_IPUT_SHORT */
8382
8383    /*
8384     * Currently:
8385     *  r0 holds resolved field
8386     *  r9 holds object
8387     */
8388.LOP_IPUT_SHORT_finish:
8389    @bl      common_squeak4
8390    mov     r1, rINST, lsr #8           @ r1<- A+
8391    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8392    and     r1, r1, #15                 @ r1<- A
8393    cmp     r9, #0                      @ check object for null
8394    GET_VREG(r0, r1)                    @ r0<- fp[A]
8395    beq     common_errNullObject        @ object was null
8396    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8397    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8398    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8399    GOTO_OPCODE(ip)                     @ jump to next instruction
8400
8401
8402/* continuation for OP_SGET */
8403
8404    /*
8405     * Continuation if the field has not yet been resolved.
8406     *  r1: BBBB field ref
8407     */
8408.LOP_SGET_resolve:
8409    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8410    EXPORT_PC()                         @ resolve() could throw, so export now
8411    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8412    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8413    cmp     r0, #0                      @ success?
8414    bne     .LOP_SGET_finish          @ yes, finish
8415    b       common_exceptionThrown      @ no, handle exception
8416
8417
8418/* continuation for OP_SGET_WIDE */
8419
8420    /*
8421     * Continuation if the field has not yet been resolved.
8422     *  r1: BBBB field ref
8423     */
8424.LOP_SGET_WIDE_resolve:
8425    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8426    EXPORT_PC()                         @ resolve() could throw, so export now
8427    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8428    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8429    cmp     r0, #0                      @ success?
8430    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8431    b       common_exceptionThrown      @ no, handle exception
8432
8433
8434/* continuation for OP_SGET_OBJECT */
8435
8436    /*
8437     * Continuation if the field has not yet been resolved.
8438     *  r1: BBBB field ref
8439     */
8440.LOP_SGET_OBJECT_resolve:
8441    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8442    EXPORT_PC()                         @ resolve() could throw, so export now
8443    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8444    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8445    cmp     r0, #0                      @ success?
8446    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8447    b       common_exceptionThrown      @ no, handle exception
8448
8449
8450/* continuation for OP_SGET_BOOLEAN */
8451
8452    /*
8453     * Continuation if the field has not yet been resolved.
8454     *  r1: BBBB field ref
8455     */
8456.LOP_SGET_BOOLEAN_resolve:
8457    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8458    EXPORT_PC()                         @ resolve() could throw, so export now
8459    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8460    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8461    cmp     r0, #0                      @ success?
8462    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8463    b       common_exceptionThrown      @ no, handle exception
8464
8465
8466/* continuation for OP_SGET_BYTE */
8467
8468    /*
8469     * Continuation if the field has not yet been resolved.
8470     *  r1: BBBB field ref
8471     */
8472.LOP_SGET_BYTE_resolve:
8473    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8474    EXPORT_PC()                         @ resolve() could throw, so export now
8475    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8476    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8477    cmp     r0, #0                      @ success?
8478    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8479    b       common_exceptionThrown      @ no, handle exception
8480
8481
8482/* continuation for OP_SGET_CHAR */
8483
8484    /*
8485     * Continuation if the field has not yet been resolved.
8486     *  r1: BBBB field ref
8487     */
8488.LOP_SGET_CHAR_resolve:
8489    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8490    EXPORT_PC()                         @ resolve() could throw, so export now
8491    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8492    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8493    cmp     r0, #0                      @ success?
8494    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8495    b       common_exceptionThrown      @ no, handle exception
8496
8497
8498/* continuation for OP_SGET_SHORT */
8499
8500    /*
8501     * Continuation if the field has not yet been resolved.
8502     *  r1: BBBB field ref
8503     */
8504.LOP_SGET_SHORT_resolve:
8505    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8506    EXPORT_PC()                         @ resolve() could throw, so export now
8507    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8508    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8509    cmp     r0, #0                      @ success?
8510    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8511    b       common_exceptionThrown      @ no, handle exception
8512
8513
8514/* continuation for OP_SPUT */
8515
8516    /*
8517     * Continuation if the field has not yet been resolved.
8518     *  r1: BBBB field ref
8519     */
8520.LOP_SPUT_resolve:
8521    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8522    EXPORT_PC()                         @ resolve() could throw, so export now
8523    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8524    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8525    cmp     r0, #0                      @ success?
8526    bne     .LOP_SPUT_finish          @ yes, finish
8527    b       common_exceptionThrown      @ no, handle exception
8528
8529
8530/* continuation for OP_SPUT_WIDE */
8531
8532    /*
8533     * Continuation if the field has not yet been resolved.
8534     *  r1: BBBB field ref
8535     *  r9: &fp[AA]
8536     */
8537.LOP_SPUT_WIDE_resolve:
8538    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8539    EXPORT_PC()                         @ resolve() could throw, so export now
8540    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8541    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8542    cmp     r0, #0                      @ success?
8543    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8544    b       common_exceptionThrown      @ no, handle exception
8545
8546
8547/* continuation for OP_SPUT_OBJECT */
8548
8549    /*
8550     * Continuation if the field has not yet been resolved.
8551     *  r1: BBBB field ref
8552     */
8553.LOP_SPUT_OBJECT_resolve:
8554    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8555    EXPORT_PC()                         @ resolve() could throw, so export now
8556    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8557    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8558    cmp     r0, #0                      @ success?
8559    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8560    b       common_exceptionThrown      @ no, handle exception
8561
8562
8563/* continuation for OP_SPUT_BOOLEAN */
8564
8565    /*
8566     * Continuation if the field has not yet been resolved.
8567     *  r1: BBBB field ref
8568     */
8569.LOP_SPUT_BOOLEAN_resolve:
8570    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8571    EXPORT_PC()                         @ resolve() could throw, so export now
8572    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8573    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8574    cmp     r0, #0                      @ success?
8575    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8576    b       common_exceptionThrown      @ no, handle exception
8577
8578
8579/* continuation for OP_SPUT_BYTE */
8580
8581    /*
8582     * Continuation if the field has not yet been resolved.
8583     *  r1: BBBB field ref
8584     */
8585.LOP_SPUT_BYTE_resolve:
8586    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8587    EXPORT_PC()                         @ resolve() could throw, so export now
8588    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8589    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8590    cmp     r0, #0                      @ success?
8591    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8592    b       common_exceptionThrown      @ no, handle exception
8593
8594
8595/* continuation for OP_SPUT_CHAR */
8596
8597    /*
8598     * Continuation if the field has not yet been resolved.
8599     *  r1: BBBB field ref
8600     */
8601.LOP_SPUT_CHAR_resolve:
8602    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8603    EXPORT_PC()                         @ resolve() could throw, so export now
8604    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8605    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8606    cmp     r0, #0                      @ success?
8607    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8608    b       common_exceptionThrown      @ no, handle exception
8609
8610
8611/* continuation for OP_SPUT_SHORT */
8612
8613    /*
8614     * Continuation if the field has not yet been resolved.
8615     *  r1: BBBB field ref
8616     */
8617.LOP_SPUT_SHORT_resolve:
8618    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8619    EXPORT_PC()                         @ resolve() could throw, so export now
8620    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8621    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8622    cmp     r0, #0                      @ success?
8623    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8624    b       common_exceptionThrown      @ no, handle exception
8625
8626
8627/* continuation for OP_INVOKE_VIRTUAL */
8628
8629    /*
8630     * At this point:
8631     *  r0 = resolved base method
8632     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8633     */
8634.LOP_INVOKE_VIRTUAL_continue:
8635    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8636    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8637    cmp     r1, #0                      @ is "this" null?
8638    beq     common_errNullObject        @ null "this", throw exception
8639    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8640    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8641    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8642    bl      common_invokeMethodNoRange @ continue on
8643
8644
8645/* continuation for OP_INVOKE_SUPER */
8646
8647    /*
8648     * At this point:
8649     *  r0 = resolved base method
8650     *  r9 = method->clazz
8651     */
8652.LOP_INVOKE_SUPER_continue:
8653    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8654    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8655    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8656    EXPORT_PC()                         @ must export for invoke
8657    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8658    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8659    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8660    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8661    bl      common_invokeMethodNoRange @ continue on
8662
8663.LOP_INVOKE_SUPER_resolve:
8664    mov     r0, r9                      @ r0<- method->clazz
8665    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8666    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8667    cmp     r0, #0                      @ got null?
8668    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8669    b       common_exceptionThrown      @ yes, handle exception
8670
8671    /*
8672     * Throw a NoSuchMethodError with the method name as the message.
8673     *  r0 = resolved base method
8674     */
8675.LOP_INVOKE_SUPER_nsm:
8676    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8677    b       common_errNoSuchMethod
8678
8679
8680/* continuation for OP_INVOKE_DIRECT */
8681
8682    /*
8683     * On entry:
8684     *  r1 = reference (BBBB or CCCC)
8685     *  r10 = "this" register
8686     */
8687.LOP_INVOKE_DIRECT_resolve:
8688    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8689    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8690    mov     r2, #METHOD_DIRECT          @ resolver method type
8691    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8692    cmp     r0, #0                      @ got null?
8693    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8694    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8695    b       common_exceptionThrown      @ yes, handle exception
8696
8697
8698/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8699
8700    /*
8701     * At this point:
8702     *  r0 = resolved base method
8703     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8704     */
8705.LOP_INVOKE_VIRTUAL_RANGE_continue:
8706    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8707    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8708    cmp     r1, #0                      @ is "this" null?
8709    beq     common_errNullObject        @ null "this", throw exception
8710    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8711    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8712    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8713    bl      common_invokeMethodRange @ continue on
8714
8715
8716/* continuation for OP_INVOKE_SUPER_RANGE */
8717
8718    /*
8719     * At this point:
8720     *  r0 = resolved base method
8721     *  r9 = method->clazz
8722     */
8723.LOP_INVOKE_SUPER_RANGE_continue:
8724    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8725    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8726    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8727    EXPORT_PC()                         @ must export for invoke
8728    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8729    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8730    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8731    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8732    bl      common_invokeMethodRange @ continue on
8733
8734.LOP_INVOKE_SUPER_RANGE_resolve:
8735    mov     r0, r9                      @ r0<- method->clazz
8736    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8737    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8738    cmp     r0, #0                      @ got null?
8739    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8740    b       common_exceptionThrown      @ yes, handle exception
8741
8742    /*
8743     * Throw a NoSuchMethodError with the method name as the message.
8744     *  r0 = resolved base method
8745     */
8746.LOP_INVOKE_SUPER_RANGE_nsm:
8747    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8748    b       common_errNoSuchMethod
8749
8750
8751/* continuation for OP_INVOKE_DIRECT_RANGE */
8752
8753    /*
8754     * On entry:
8755     *  r1 = reference (BBBB or CCCC)
8756     *  r10 = "this" register
8757     */
8758.LOP_INVOKE_DIRECT_RANGE_resolve:
8759    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8760    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8761    mov     r2, #METHOD_DIRECT          @ resolver method type
8762    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8763    cmp     r0, #0                      @ got null?
8764    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8765    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8766    b       common_exceptionThrown      @ yes, handle exception
8767
8768
8769/* continuation for OP_FLOAT_TO_LONG */
8770/*
8771 * Convert the float in r0 to a long in r0/r1.
8772 *
8773 * We have to clip values to long min/max per the specification.  The
8774 * expected common case is a "reasonable" value that converts directly
8775 * to modest integer.  The EABI convert function isn't doing this for us.
8776 */
8777f2l_doconv:
8778    stmfd   sp!, {r4, lr}
8779    mov     r1, #0x5f000000             @ (float)maxlong
8780    mov     r4, r0
8781    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8782    cmp     r0, #0                      @ nonzero == yes
8783    mvnne   r0, #0                      @ return maxlong (7fffffff)
8784    mvnne   r1, #0x80000000
8785    ldmnefd sp!, {r4, pc}
8786
8787    mov     r0, r4                      @ recover arg
8788    mov     r1, #0xdf000000             @ (float)minlong
8789    bl      __aeabi_fcmple              @ is arg <= minlong?
8790    cmp     r0, #0                      @ nonzero == yes
8791    movne   r0, #0                      @ return minlong (80000000)
8792    movne   r1, #0x80000000
8793    ldmnefd sp!, {r4, pc}
8794
8795    mov     r0, r4                      @ recover arg
8796    mov     r1, r4
8797    bl      __aeabi_fcmpeq              @ is arg == self?
8798    cmp     r0, #0                      @ zero == no
8799    moveq   r1, #0                      @ return zero for NaN
8800    ldmeqfd sp!, {r4, pc}
8801
8802    mov     r0, r4                      @ recover arg
8803    bl      __aeabi_f2lz                @ convert float to long
8804    ldmfd   sp!, {r4, pc}
8805
8806
8807/* continuation for OP_DOUBLE_TO_LONG */
8808/*
8809 * Convert the double in r0/r1 to a long in r0/r1.
8810 *
8811 * We have to clip values to long min/max per the specification.  The
8812 * expected common case is a "reasonable" value that converts directly
8813 * to modest integer.  The EABI convert function isn't doing this for us.
8814 */
8815d2l_doconv:
8816    stmfd   sp!, {r4, r5, lr}           @ save regs
8817    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8818    add     r3, #0x00e00000             @  0x43e00000
8819    mov     r2, #0                      @ maxlong, as a double (low word)
8820    sub     sp, sp, #4                  @ align for EABI
8821    mov     r4, r0                      @ save a copy of r0
8822    mov     r5, r1                      @  and r1
8823    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8824    cmp     r0, #0                      @ nonzero == yes
8825    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8826    mvnne   r1, #0x80000000
8827    bne     1f
8828
8829    mov     r0, r4                      @ recover arg
8830    mov     r1, r5
8831    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8832    add     r3, #0x00e00000             @  0xc3e00000
8833    mov     r2, #0                      @ minlong, as a double (low word)
8834    bl      __aeabi_dcmple              @ is arg <= minlong?
8835    cmp     r0, #0                      @ nonzero == yes
8836    movne   r0, #0                      @ return minlong (8000000000000000)
8837    movne   r1, #0x80000000
8838    bne     1f
8839
8840    mov     r0, r4                      @ recover arg
8841    mov     r1, r5
8842    mov     r2, r4                      @ compare against self
8843    mov     r3, r5
8844    bl      __aeabi_dcmpeq              @ is arg == self?
8845    cmp     r0, #0                      @ zero == no
8846    moveq   r1, #0                      @ return zero for NaN
8847    beq     1f
8848
8849    mov     r0, r4                      @ recover arg
8850    mov     r1, r5
8851    bl      __aeabi_d2lz                @ convert double to long
8852
88531:
8854    add     sp, sp, #4
8855    ldmfd   sp!, {r4, r5, pc}
8856
8857
8858/* continuation for OP_MUL_LONG */
8859
8860.LOP_MUL_LONG_finish:
8861    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8862    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8863    GOTO_OPCODE(ip)                     @ jump to next instruction
8864
8865
8866/* continuation for OP_SHL_LONG */
8867
8868.LOP_SHL_LONG_finish:
8869    mov     r0, r0, asl r2              @  r0<- r0 << r2
8870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8871    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8872    GOTO_OPCODE(ip)                     @ jump to next instruction
8873
8874
8875/* continuation for OP_SHR_LONG */
8876
8877.LOP_SHR_LONG_finish:
8878    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8880    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8881    GOTO_OPCODE(ip)                     @ jump to next instruction
8882
8883
8884/* continuation for OP_USHR_LONG */
8885
8886.LOP_USHR_LONG_finish:
8887    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8889    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8890    GOTO_OPCODE(ip)                     @ jump to next instruction
8891
8892
8893/* continuation for OP_SHL_LONG_2ADDR */
8894
8895.LOP_SHL_LONG_2ADDR_finish:
8896    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8897    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8898    GOTO_OPCODE(ip)                     @ jump to next instruction
8899
8900
8901/* continuation for OP_SHR_LONG_2ADDR */
8902
8903.LOP_SHR_LONG_2ADDR_finish:
8904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8905    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8906    GOTO_OPCODE(ip)                     @ jump to next instruction
8907
8908
8909/* continuation for OP_USHR_LONG_2ADDR */
8910
8911.LOP_USHR_LONG_2ADDR_finish:
8912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8913    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8914    GOTO_OPCODE(ip)                     @ jump to next instruction
8915
8916
8917/* continuation for OP_EXECUTE_INLINE */
8918
8919    /*
8920     * Extract args, call function.
8921     *  r0 = #of args (0-4)
8922     *  r10 = call index
8923     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8924     *
8925     * Other ideas:
8926     * - Use a jump table from the main piece to jump directly into the
8927     *   AND/LDR pairs.  Costs a data load, saves a branch.
8928     * - Have five separate pieces that do the loading, so we can work the
8929     *   interleave a little better.  Increases code size.
8930     */
8931.LOP_EXECUTE_INLINE_continue:
8932    rsb     r0, r0, #4                  @ r0<- 4-r0
8933    FETCH(r9, 2)                        @ r9<- FEDC
8934    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8935    bl      common_abort                @ (skipped due to ARM prefetch)
89364:  and     ip, r9, #0xf000             @ isolate F
8937    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
89383:  and     ip, r9, #0x0f00             @ isolate E
8939    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
89402:  and     ip, r9, #0x00f0             @ isolate D
8941    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
89421:  and     ip, r9, #0x000f             @ isolate C
8943    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
89440:
8945    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
8946    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8947    @ (not reached)
8948
8949.LOP_EXECUTE_INLINE_table:
8950    .word   gDvmInlineOpsTable
8951
8952
8953/* continuation for OP_EXECUTE_INLINE_RANGE */
8954
8955    /*
8956     * Extract args, call function.
8957     *  r0 = #of args (0-4)
8958     *  r10 = call index
8959     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
8960     */
8961.LOP_EXECUTE_INLINE_RANGE_continue:
8962    rsb     r0, r0, #4                  @ r0<- 4-r0
8963    FETCH(r9, 2)                        @ r9<- CCCC
8964    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
8965    bl      common_abort                @ (skipped due to ARM prefetch)
89664:  add     ip, r9, #3                  @ base+3
8967    GET_VREG(r3, ip)                    @ r3<- vBase[3]
89683:  add     ip, r9, #2                  @ base+2
8969    GET_VREG(r2, ip)                    @ r2<- vBase[2]
89702:  add     ip, r9, #1                  @ base+1
8971    GET_VREG(r1, ip)                    @ r1<- vBase[1]
89721:  add     ip, r9, #0                  @ (nop)
8973    GET_VREG(r0, ip)                    @ r0<- vBase[0]
89740:
8975    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
8976    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
8977    @ (not reached)
8978
8979.LOP_EXECUTE_INLINE_RANGE_table:
8980    .word   gDvmInlineOpsTable
8981
8982
8983    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8984    .global dvmAsmSisterEnd
8985dvmAsmSisterEnd:
8986
8987/* File: armv5te/footer.S */
8988
8989/*
8990 * ===========================================================================
8991 *  Common subroutines and data
8992 * ===========================================================================
8993 */
8994
8995
8996
8997    .text
8998    .align  2
8999
9000#if defined(WITH_JIT)
9001#if defined(WITH_SELF_VERIFICATION)
9002    .global dvmJitToInterpPunt
9003dvmJitToInterpPunt:
9004    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9005    b      dvmJitSelfVerificationEnd    @ doesn't return
9006
9007    .global dvmJitToInterpSingleStep
9008dvmJitToInterpSingleStep:
9009    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9010    b      dvmJitSelfVerificationEnd    @ doesn't return
9011
9012    .global dvmJitToInterpTraceSelectNoChain
9013dvmJitToInterpTraceSelectNoChain:
9014    mov    r0,rPC                       @ pass our target PC
9015    mov    r2,#kSVSTraceSelectNoChain   @ r2<- interpreter entry point
9016    b      dvmJitSelfVerificationEnd    @ doesn't return
9017
9018    .global dvmJitToInterpTraceSelect
9019dvmJitToInterpTraceSelect:
9020    ldr    r0,[lr, #-1]                 @ pass our target PC
9021    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9022    b      dvmJitSelfVerificationEnd    @ doesn't return
9023
9024    .global dvmJitToInterpBackwardBranch
9025dvmJitToInterpBackwardBranch:
9026    ldr    r0,[lr, #-1]                 @ pass our target PC
9027    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9028    b      dvmJitSelfVerificationEnd    @ doesn't return
9029
9030    .global dvmJitToInterpNormal
9031dvmJitToInterpNormal:
9032    ldr    r0,[lr, #-1]                 @ pass our target PC
9033    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9034    b      dvmJitSelfVerificationEnd    @ doesn't return
9035
9036    .global dvmJitToInterpNoChain
9037dvmJitToInterpNoChain:
9038    mov    r0,rPC                       @ pass our target PC
9039    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9040    b      dvmJitSelfVerificationEnd    @ doesn't return
9041#else
9042/*
9043 * Return from the translation cache to the interpreter when the compiler is
9044 * having issues translating/executing a Dalvik instruction. We have to skip
9045 * the code cache lookup otherwise it is possible to indefinitely bouce
9046 * between the interpreter and the code cache if the instruction that fails
9047 * to be compiled happens to be at a trace start.
9048 */
9049    .global dvmJitToInterpPunt
9050dvmJitToInterpPunt:
9051    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9052    mov    rPC, r0
9053#ifdef JIT_STATS
9054    mov    r0,lr
9055    bl     dvmBumpPunt;
9056#endif
9057    EXPORT_PC()
9058    mov    r0, #0
9059    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9060    adrl   rIBASE, dvmAsmInstructionStart
9061    FETCH_INST()
9062    GET_INST_OPCODE(ip)
9063    GOTO_OPCODE(ip)
9064
9065/*
9066 * Return to the interpreter to handle a single instruction.
9067 * On entry:
9068 *    r0 <= PC
9069 *    r1 <= PC of resume instruction
9070 *    lr <= resume point in translation
9071 */
9072    .global dvmJitToInterpSingleStep
9073dvmJitToInterpSingleStep:
9074    str    lr,[rGLUE,#offGlue_jitResume]
9075    str    r1,[rGLUE,#offGlue_jitResumePC]
9076    mov    r1,#kInterpEntryInstr
9077    @ enum is 4 byte in aapcs-EABI
9078    str    r1, [rGLUE, #offGlue_entryPoint]
9079    mov    rPC,r0
9080    EXPORT_PC()
9081
9082    adrl   rIBASE, dvmAsmInstructionStart
9083    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9084    str    r2,[rGLUE,#offGlue_jitState]
9085    mov    r1,#1                  @ set changeInterp to bail to debug interp
9086    b      common_gotoBail
9087
9088/*
9089 * Return from the translation cache and immediately request
9090 * a translation for the exit target.  Commonly used for callees.
9091 */
9092    .global dvmJitToInterpTraceSelectNoChain
9093dvmJitToInterpTraceSelectNoChain:
9094#ifdef JIT_STATS
9095    bl     dvmBumpNoChain
9096#endif
9097    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9098    mov    r0,rPC
9099    bl     dvmJitGetCodeAddr        @ Is there a translation?
9100    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9101    mov    r1, rPC                  @ arg1 of translation may need this
9102    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9103    cmp    r0,#0
9104    bxne   r0                       @ continue native execution if so
9105    b      2f
9106
9107/*
9108 * Return from the translation cache and immediately request
9109 * a translation for the exit target.  Commonly used following
9110 * invokes.
9111 */
9112    .global dvmJitToInterpTraceSelect
9113dvmJitToInterpTraceSelect:
9114    ldr    rPC,[lr, #-1]           @ get our target PC
9115    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9116    add    rINST,lr,#-5            @ save start of chain branch
9117    mov    r0,rPC
9118    bl     dvmJitGetCodeAddr       @ Is there a translation?
9119    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9120    cmp    r0,#0
9121    beq    2f
9122    mov    r1,rINST
9123    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9124    mov    r1, rPC                  @ arg1 of translation may need this
9125    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9126    cmp    r0,#0                    @ successful chain?
9127    bxne   r0                       @ continue native execution
9128    b      toInterpreter            @ didn't chain - resume with interpreter
9129
9130/* No translation, so request one if profiling isn't disabled*/
91312:
9132    adrl   rIBASE, dvmAsmInstructionStart
9133    GET_JIT_PROF_TABLE(r0)
9134    FETCH_INST()
9135    cmp    r0, #0
9136    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9137    bne    common_selectTrace
9138    GET_INST_OPCODE(ip)
9139    GOTO_OPCODE(ip)
9140
9141/*
9142 * Return from the translation cache to the interpreter.
9143 * The return was done with a BLX from thumb mode, and
9144 * the following 32-bit word contains the target rPC value.
9145 * Note that lr (r14) will have its low-order bit set to denote
9146 * its thumb-mode origin.
9147 *
9148 * We'll need to stash our lr origin away, recover the new
9149 * target and then check to see if there is a translation available
9150 * for our new target.  If so, we do a translation chain and
9151 * go back to native execution.  Otherwise, it's back to the
9152 * interpreter (after treating this entry as a potential
9153 * trace start).
9154 */
9155    .global dvmJitToInterpNormal
9156dvmJitToInterpNormal:
9157    ldr    rPC,[lr, #-1]           @ get our target PC
9158    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9159    add    rINST,lr,#-5            @ save start of chain branch
9160#ifdef JIT_STATS
9161    bl     dvmBumpNormal
9162#endif
9163    mov    r0,rPC
9164    bl     dvmJitGetCodeAddr        @ Is there a translation?
9165    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9166    cmp    r0,#0
9167    beq    toInterpreter            @ go if not, otherwise do chain
9168    mov    r1,rINST
9169    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9170    mov    r1, rPC                  @ arg1 of translation may need this
9171    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9172    cmp    r0,#0                    @ successful chain?
9173    bxne   r0                       @ continue native execution
9174    b      toInterpreter            @ didn't chain - resume with interpreter
9175
9176/*
9177 * Return from the translation cache to the interpreter to do method invocation.
9178 * Check if translation exists for the callee, but don't chain to it.
9179 */
9180    .global dvmJitToInterpNoChain
9181dvmJitToInterpNoChain:
9182#ifdef JIT_STATS
9183    bl     dvmBumpNoChain
9184#endif
9185    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9186    mov    r0,rPC
9187    bl     dvmJitGetCodeAddr        @ Is there a translation?
9188    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9189    mov    r1, rPC                  @ arg1 of translation may need this
9190    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9191    cmp    r0,#0
9192    bxne   r0                       @ continue native execution if so
9193#endif
9194
9195/*
9196 * No translation, restore interpreter regs and start interpreting.
9197 * rGLUE & rFP were preserved in the translated code, and rPC has
9198 * already been restored by the time we get here.  We'll need to set
9199 * up rIBASE & rINST, and load the address of the JitTable into r0.
9200 */
9201toInterpreter:
9202    EXPORT_PC()
9203    adrl   rIBASE, dvmAsmInstructionStart
9204    FETCH_INST()
9205    GET_JIT_PROF_TABLE(r0)
9206    @ NOTE: intended fallthrough
9207/*
9208 * Common code to update potential trace start counter, and initiate
9209 * a trace-build if appropriate.  On entry, rPC should point to the
9210 * next instruction to execute, and rINST should be already loaded with
9211 * the next opcode word, and r0 holds a pointer to the jit profile
9212 * table (pJitProfTable).
9213 */
9214common_testUpdateProfile:
9215    cmp     r0,#0
9216    GET_INST_OPCODE(ip)
9217    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9218
9219common_updateProfile:
9220    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9221    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9222    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9223    GET_INST_OPCODE(ip)
9224    subs    r1,r1,#1           @ decrement counter
9225    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9226    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9227
9228/*
9229 * Here, we switch to the debug interpreter to request
9230 * trace selection.  First, though, check to see if there
9231 * is already a native translation in place (and, if so,
9232 * jump to it now).
9233 */
9234    GET_JIT_THRESHOLD(r1)
9235    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9236    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9237    EXPORT_PC()
9238    mov     r0,rPC
9239    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9240    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9241    mov     r1, rPC                     @ arg1 of translation may need this
9242    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9243    cmp     r0,#0
9244#if !defined(WITH_SELF_VERIFICATION)
9245    bxne    r0                          @ jump to the translation
9246    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9247    @ fall-through to common_selectTrace
9248#else
9249    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9250    beq     common_selectTrace
9251    /*
9252     * At this point, we have a target translation.  However, if
9253     * that translation is actually the interpret-only pseudo-translation
9254     * we want to treat it the same as no translation.
9255     */
9256    mov     r10, r0                      @ save target
9257    bl      dvmCompilerGetInterpretTemplate
9258    cmp     r0, r10                      @ special case?
9259    bne     dvmJitSelfVerificationStart  @ set up self verification
9260    GET_INST_OPCODE(ip)
9261    GOTO_OPCODE(ip)
9262    /* no return */
9263#endif
9264
9265/*
9266 * On entry:
9267 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9268 */
9269common_selectTrace:
9270    str     r2,[rGLUE,#offGlue_jitState]
9271    mov     r2,#kInterpEntryInstr       @ normal entry reason
9272    str     r2,[rGLUE,#offGlue_entryPoint]
9273    mov     r1,#1                       @ set changeInterp
9274    b       common_gotoBail
9275
9276#if defined(WITH_SELF_VERIFICATION)
9277/*
9278 * Save PC and registers to shadow memory for self verification mode
9279 * before jumping to native translation.
9280 * On entry, r10 contains the address of the target translation.
9281 */
9282dvmJitSelfVerificationStart:
9283    mov     r0,rPC                      @ r0<- program counter
9284    mov     r1,rFP                      @ r1<- frame pointer
9285    mov     r2,rGLUE                    @ r2<- InterpState pointer
9286    mov     r3,r10                      @ r3<- target translation
9287    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9288    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9289    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9290    bx      r10                         @ jump to the translation
9291
9292/*
9293 * Restore PC, registers, and interpState to original values
9294 * before jumping back to the interpreter.
9295 */
9296dvmJitSelfVerificationEnd:
9297    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9298    mov    r1, #0
9299    str    r1, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9300    mov    r1,rFP                        @ pass ending fp
9301    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9302    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9303    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9304    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9305    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9306    cmp    r1,#0                         @ check for punt condition
9307    beq    1f
9308    mov    r2,#kJitSelfVerification      @ ask for self verification
9309    str    r2,[rGLUE,#offGlue_jitState]
9310    mov    r2,#kInterpEntryInstr         @ normal entry reason
9311    str    r2,[rGLUE,#offGlue_entryPoint]
9312    mov    r1,#1                         @ set changeInterp
9313    b      common_gotoBail
9314
93151:                                       @ exit to interpreter without check
9316    EXPORT_PC()
9317    adrl   rIBASE, dvmAsmInstructionStart
9318    FETCH_INST()
9319    GET_INST_OPCODE(ip)
9320    GOTO_OPCODE(ip)
9321#endif
9322
9323#endif
9324
9325/*
9326 * Common code when a backward branch is taken.
9327 *
9328 * On entry:
9329 *  r9 is PC adjustment *in bytes*
9330 */
9331common_backwardBranch:
9332    mov     r0, #kInterpEntryInstr
9333    bl      common_periodicChecks
9334#if defined(WITH_JIT)
9335    GET_JIT_PROF_TABLE(r0)
9336    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9337    cmp     r0,#0
9338    bne     common_updateProfile
9339    GET_INST_OPCODE(ip)
9340    GOTO_OPCODE(ip)
9341#else
9342    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9343    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9344    GOTO_OPCODE(ip)                     @ jump to next instruction
9345#endif
9346
9347
9348/*
9349 * Need to see if the thread needs to be suspended or debugger/profiler
9350 * activity has begun.
9351 *
9352 * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
9353 * have to do the second ldr.
9354 *
9355 * TODO: reduce this so we're just checking a single location.
9356 *
9357 * On entry:
9358 *  r0 is reentry type, e.g. kInterpEntryInstr
9359 *  r9 is trampoline PC adjustment *in bytes*
9360 */
9361common_periodicChecks:
9362    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9363
9364    @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
9365    str     r0, [rGLUE, #offGlue_entryPoint]
9366
9367#if defined(WITH_DEBUGGER)
9368    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9369#endif
9370#if defined(WITH_PROFILER)
9371    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9372#endif
9373
9374    ldr     r3, [r3]                    @ r3<- suspendCount (int)
9375
9376#if defined(WITH_DEBUGGER)
9377    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
9378#endif
9379#if defined (WITH_PROFILER)
9380    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9381#endif
9382
9383    cmp     r3, #0                      @ suspend pending?
9384    bne     2f                          @ yes, do full suspension check
9385
9386#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9387# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9388    orrs    r1, r1, r2                  @ r1<- r1 | r2
9389    cmp     r1, #0                      @ debugger attached or profiler started?
9390# elif defined(WITH_DEBUGGER)
9391    cmp     r1, #0                      @ debugger attached?
9392# elif defined(WITH_PROFILER)
9393    cmp     r2, #0                      @ profiler started?
9394# endif
9395    bne     3f                          @ debugger/profiler, switch interp
9396#endif
9397
9398    bx      lr                          @ nothing to do, return
9399
94002:  @ check suspend
9401#if defined(WITH_JIT)
9402    /*
9403     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9404     * doubles as the Jit's on/off switch.
9405     */
9406    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r10<-&gDvmJit.pJitProfTable
9407    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9408    ldr     r3, [r3] @ r10 <- pJitProfTable
9409    EXPORT_PC()                         @ need for precise GC
9410    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9411#else
9412    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9413    EXPORT_PC()                         @ need for precise GC
9414#endif
9415    b       dvmCheckSuspendPending      @ suspend if necessary, then return
9416
94173:  @ debugger/profiler enabled, bail out
9418    add     rPC, rPC, r9                @ update rPC
9419    mov     r1, #1                      @ "want switch" = true
9420    b       common_gotoBail
9421
9422
9423/*
9424 * The equivalent of "goto bail", this calls through the "bail handler".
9425 *
9426 * State registers will be saved to the "glue" area before bailing.
9427 *
9428 * On entry:
9429 *  r1 is "bool changeInterp", indicating if we want to switch to the
9430 *     other interpreter or just bail all the way out
9431 */
9432common_gotoBail:
9433    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9434    mov     r0, rGLUE                   @ r0<- glue ptr
9435    b       dvmMterpStdBail             @ call(glue, changeInterp)
9436
9437    @add     r1, r1, #1                  @ using (boolean+1)
9438    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9439    @bl      _longjmp                    @ does not return
9440    @bl      common_abort
9441
9442
9443/*
9444 * Common code for method invocation with range.
9445 *
9446 * On entry:
9447 *  r0 is "Method* methodToCall", the method we're trying to call
9448 */
9449common_invokeMethodRange:
9450.LinvokeNewRange:
9451    @ prepare to copy args to "outs" area of current frame
9452    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9453    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9454    beq     .LinvokeArgsDone            @ if no args, skip the rest
9455    FETCH(r1, 2)                        @ r1<- CCCC
9456
9457    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9458    @ (very few methods have > 10 args; could unroll for common cases)
9459    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9460    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9461    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
94621:  ldr     r1, [r3], #4                @ val = *fp++
9463    subs    r2, r2, #1                  @ count--
9464    str     r1, [r10], #4               @ *outs++ = val
9465    bne     1b                          @ ...while count != 0
9466    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9467    b       .LinvokeArgsDone
9468
9469/*
9470 * Common code for method invocation without range.
9471 *
9472 * On entry:
9473 *  r0 is "Method* methodToCall", the method we're trying to call
9474 */
9475common_invokeMethodNoRange:
9476.LinvokeNewNoRange:
9477    @ prepare to copy args to "outs" area of current frame
9478    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9479    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9480    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9481    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9482    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9483    beq     .LinvokeArgsDone
9484
9485    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9486.LinvokeNonRange:
9487    rsb     r2, r2, #5                  @ r2<- 5-r2
9488    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9489    bl      common_abort                @ (skipped due to ARM prefetch)
94905:  and     ip, rINST, #0x0f00          @ isolate A
9491    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9492    mov     r0, r0                      @ nop
9493    str     r2, [r10, #-4]!             @ *--outs = vA
94944:  and     ip, r1, #0xf000             @ isolate G
9495    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9496    mov     r0, r0                      @ nop
9497    str     r2, [r10, #-4]!             @ *--outs = vG
94983:  and     ip, r1, #0x0f00             @ isolate F
9499    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9500    mov     r0, r0                      @ nop
9501    str     r2, [r10, #-4]!             @ *--outs = vF
95022:  and     ip, r1, #0x00f0             @ isolate E
9503    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9504    mov     r0, r0                      @ nop
9505    str     r2, [r10, #-4]!             @ *--outs = vE
95061:  and     ip, r1, #0x000f             @ isolate D
9507    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9508    mov     r0, r0                      @ nop
9509    str     r2, [r10, #-4]!             @ *--outs = vD
95100:  @ fall through to .LinvokeArgsDone
9511
9512.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9513    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9514    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9515    @ find space for the new stack frame, check for overflow
9516    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9517    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9518    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9519@    bl      common_dumpRegs
9520    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9521    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9522    cmp     r3, r9                      @ bottom < interpStackEnd?
9523    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9524    blt     .LstackOverflow             @ yes, this frame will overflow stack
9525
9526    @ set up newSaveArea
9527#ifdef EASY_GDB
9528    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9529    str     ip, [r10, #offStackSaveArea_prevSave]
9530#endif
9531    str     rFP, [r10, #offStackSaveArea_prevFrame]
9532    str     rPC, [r10, #offStackSaveArea_savedPc]
9533#if defined(WITH_JIT)
9534    mov     r9, #0
9535    str     r9, [r10, #offStackSaveArea_returnAddr]
9536#endif
9537    str     r0, [r10, #offStackSaveArea_method]
9538    tst     r3, #ACC_NATIVE
9539    bne     .LinvokeNative
9540
9541    /*
9542    stmfd   sp!, {r0-r3}
9543    bl      common_printNewline
9544    mov     r0, rFP
9545    mov     r1, #0
9546    bl      dvmDumpFp
9547    ldmfd   sp!, {r0-r3}
9548    stmfd   sp!, {r0-r3}
9549    mov     r0, r1
9550    mov     r1, r10
9551    bl      dvmDumpFp
9552    bl      common_printNewline
9553    ldmfd   sp!, {r0-r3}
9554    */
9555
9556    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9557    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9558    mov     rPC, r2                         @ publish new rPC
9559    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9560
9561    @ Update "glue" values for the new method
9562    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9563    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9564    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9565#if defined(WITH_JIT)
9566    GET_JIT_PROF_TABLE(r0)
9567    mov     rFP, r1                         @ fp = newFp
9568    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9569    mov     rINST, r9                       @ publish new rINST
9570    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9571    cmp     r0,#0
9572    bne     common_updateProfile
9573    GOTO_OPCODE(ip)                         @ jump to next instruction
9574#else
9575    mov     rFP, r1                         @ fp = newFp
9576    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9577    mov     rINST, r9                       @ publish new rINST
9578    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9579    GOTO_OPCODE(ip)                         @ jump to next instruction
9580#endif
9581
9582.LinvokeNative:
9583    @ Prep for the native call
9584    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9585    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9586    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9587    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9588    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9589    mov     r9, r3                      @ r9<- glue->self (preserve)
9590
9591    mov     r2, r0                      @ r2<- methodToCall
9592    mov     r0, r1                      @ r0<- newFp (points to args)
9593    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
9594
9595#ifdef ASSIST_DEBUGGER
9596    /* insert fake function header to help gdb find the stack frame */
9597    b       .Lskip
9598    .type   dalvik_mterp, %function
9599dalvik_mterp:
9600    .fnstart
9601    MTERP_ENTRY1
9602    MTERP_ENTRY2
9603.Lskip:
9604#endif
9605
9606    @mov     lr, pc                      @ set return addr
9607    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
9608    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
9609
9610#if defined(WITH_JIT)
9611    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
9612#endif
9613
9614    @ native return; r9=self, r10=newSaveArea
9615    @ equivalent to dvmPopJniLocals
9616    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
9617    ldr     r1, [r9, #offThread_exception] @ check for exception
9618#if defined(WITH_JIT)
9619    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
9620#endif
9621    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
9622    cmp     r1, #0                      @ null?
9623    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
9624#if defined(WITH_JIT)
9625    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
9626#endif
9627    bne     common_exceptionThrown      @ no, handle exception
9628
9629    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
9630    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9631    GOTO_OPCODE(ip)                     @ jump to next instruction
9632
9633.LstackOverflow:    @ r0=methodToCall
9634    mov     r1, r0                      @ r1<- methodToCall
9635    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
9636    bl      dvmHandleStackOverflow
9637    b       common_exceptionThrown
9638#ifdef ASSIST_DEBUGGER
9639    .fnend
9640#endif
9641
9642
9643    /*
9644     * Common code for method invocation, calling through "glue code".
9645     *
9646     * TODO: now that we have range and non-range invoke handlers, this
9647     *       needs to be split into two.  Maybe just create entry points
9648     *       that set r9 and jump here?
9649     *
9650     * On entry:
9651     *  r0 is "Method* methodToCall", the method we're trying to call
9652     *  r9 is "bool methodCallRange", indicating if this is a /range variant
9653     */
9654     .if    0
9655.LinvokeOld:
9656    sub     sp, sp, #8                  @ space for args + pad
9657    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
9658    mov     r2, r0                      @ A2<- methodToCall
9659    mov     r0, rGLUE                   @ A0<- glue
9660    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9661    mov     r1, r9                      @ A1<- methodCallRange
9662    mov     r3, rINST, lsr #8           @ A3<- AA
9663    str     ip, [sp, #0]                @ A4<- ip
9664    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
9665    add     sp, sp, #8                  @ remove arg area
9666    b       common_resumeAfterGlueCall  @ continue to next instruction
9667    .endif
9668
9669
9670
9671/*
9672 * Common code for handling a return instruction.
9673 *
9674 * This does not return.
9675 */
9676common_returnFromMethod:
9677.LreturnNew:
9678    mov     r0, #kInterpEntryReturn
9679    mov     r9, #0
9680    bl      common_periodicChecks
9681
9682    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
9683    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
9684    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
9685    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
9686                                        @ r2<- method we're returning to
9687    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
9688    cmp     r2, #0                      @ is this a break frame?
9689    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
9690    mov     r1, #0                      @ "want switch" = false
9691    beq     common_gotoBail             @ break frame, bail out completely
9692
9693    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
9694    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
9695    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
9696    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
9697#if defined(WITH_JIT)
9698    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
9699    GET_JIT_PROF_TABLE(r0)
9700    mov     rPC, r9                     @ publish new rPC
9701    str     r1, [rGLUE, #offGlue_methodClassDex]
9702    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
9703    cmp     r10, #0                      @ caller is compiled code
9704    blxne   r10
9705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9706    cmp     r0,#0
9707    bne     common_updateProfile
9708    GOTO_OPCODE(ip)                     @ jump to next instruction
9709#else
9710    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9711    mov     rPC, r9                     @ publish new rPC
9712    str     r1, [rGLUE, #offGlue_methodClassDex]
9713    GOTO_OPCODE(ip)                     @ jump to next instruction
9714#endif
9715
9716    /*
9717     * Return handling, calls through "glue code".
9718     */
9719     .if    0
9720.LreturnOld:
9721    SAVE_PC_FP_TO_GLUE()                @ export state
9722    mov     r0, rGLUE                   @ arg to function
9723    bl      dvmMterp_returnFromMethod
9724    b       common_resumeAfterGlueCall
9725    .endif
9726
9727
9728/*
9729 * Somebody has thrown an exception.  Handle it.
9730 *
9731 * If the exception processing code returns to us (instead of falling
9732 * out of the interpreter), continue with whatever the next instruction
9733 * now happens to be.
9734 *
9735 * This does not return.
9736 */
9737     .global dvmMterpCommonExceptionThrown
9738dvmMterpCommonExceptionThrown:
9739common_exceptionThrown:
9740.LexceptionNew:
9741    mov     r0, #kInterpEntryThrow
9742    mov     r9, #0
9743    bl      common_periodicChecks
9744
9745    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
9746    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
9747    mov     r1, r10                     @ r1<- self
9748    mov     r0, r9                      @ r0<- exception
9749    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
9750    mov     r3, #0                      @ r3<- NULL
9751    str     r3, [r10, #offThread_exception] @ self->exception = NULL
9752
9753    /* set up args and a local for "&fp" */
9754    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
9755    str     rFP, [sp, #-4]!             @ *--sp = fp
9756    mov     ip, sp                      @ ip<- &fp
9757    mov     r3, #0                      @ r3<- false
9758    str     ip, [sp, #-4]!              @ *--sp = &fp
9759    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
9760    mov     r0, r10                     @ r0<- self
9761    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
9762    mov     r2, r9                      @ r2<- exception
9763    sub     r1, rPC, r1                 @ r1<- pc - method->insns
9764    mov     r1, r1, asr #1              @ r1<- offset in code units
9765
9766    /* call, r0 gets catchRelPc (a code-unit offset) */
9767    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
9768
9769    /* fix earlier stack overflow if necessary; may trash rFP */
9770    ldrb    r1, [r10, #offThread_stackOverflowed]
9771    cmp     r1, #0                      @ did we overflow earlier?
9772    beq     1f                          @ no, skip ahead
9773    mov     rFP, r0                     @ save relPc result in rFP
9774    mov     r0, r10                     @ r0<- self
9775    mov     r1, r9                      @ r1<- exception
9776    bl      dvmCleanupStackOverflow     @ call(self)
9777    mov     r0, rFP                     @ restore result
97781:
9779
9780    /* update frame pointer and check result from dvmFindCatchBlock */
9781    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
9782    cmp     r0, #0                      @ is catchRelPc < 0?
9783    add     sp, sp, #8                  @ restore stack
9784    bmi     .LnotCaughtLocally
9785
9786    /* adjust locals to match self->curFrame and updated PC */
9787    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
9788    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
9789    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
9790    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
9791    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
9792    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
9793    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
9794    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
9795
9796    /* release the tracked alloc on the exception */
9797    mov     r0, r9                      @ r0<- exception
9798    mov     r1, r10                     @ r1<- self
9799    bl      dvmReleaseTrackedAlloc      @ release the exception
9800
9801    /* restore the exception if the handler wants it */
9802    FETCH_INST()                        @ load rINST from rPC
9803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9804    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
9805    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
9806    GOTO_OPCODE(ip)                     @ jump to next instruction
9807
9808.LnotCaughtLocally: @ r9=exception, r10=self
9809    /* fix stack overflow if necessary */
9810    ldrb    r1, [r10, #offThread_stackOverflowed]
9811    cmp     r1, #0                      @ did we overflow earlier?
9812    movne   r0, r10                     @ if yes: r0<- self
9813    movne   r1, r9                      @ if yes: r1<- exception
9814    blne    dvmCleanupStackOverflow     @ if yes: call(self)
9815
9816    @ may want to show "not caught locally" debug messages here
9817#if DVM_SHOW_EXCEPTION >= 2
9818    /* call __android_log_print(prio, tag, format, ...) */
9819    /* "Exception %s from %s:%d not caught locally" */
9820    @ dvmLineNumFromPC(method, pc - method->insns)
9821    ldr     r0, [rGLUE, #offGlue_method]
9822    ldr     r1, [r0, #offMethod_insns]
9823    sub     r1, rPC, r1
9824    asr     r1, r1, #1
9825    bl      dvmLineNumFromPC
9826    str     r0, [sp, #-4]!
9827    @ dvmGetMethodSourceFile(method)
9828    ldr     r0, [rGLUE, #offGlue_method]
9829    bl      dvmGetMethodSourceFile
9830    str     r0, [sp, #-4]!
9831    @ exception->clazz->descriptor
9832    ldr     r3, [r9, #offObject_clazz]
9833    ldr     r3, [r3, #offClassObject_descriptor]
9834    @
9835    ldr     r2, strExceptionNotCaughtLocally
9836    ldr     r1, strLogTag
9837    mov     r0, #3                      @ LOG_DEBUG
9838    bl      __android_log_print
9839#endif
9840    str     r9, [r10, #offThread_exception] @ restore exception
9841    mov     r0, r9                      @ r0<- exception
9842    mov     r1, r10                     @ r1<- self
9843    bl      dvmReleaseTrackedAlloc      @ release the exception
9844    mov     r1, #0                      @ "want switch" = false
9845    b       common_gotoBail             @ bail out
9846
9847
9848    /*
9849     * Exception handling, calls through "glue code".
9850     */
9851    .if     0
9852.LexceptionOld:
9853    SAVE_PC_FP_TO_GLUE()                @ export state
9854    mov     r0, rGLUE                   @ arg to function
9855    bl      dvmMterp_exceptionThrown
9856    b       common_resumeAfterGlueCall
9857    .endif
9858
9859
9860/*
9861 * After returning from a "glued" function, pull out the updated
9862 * values and start executing at the next instruction.
9863 */
9864common_resumeAfterGlueCall:
9865    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
9866    FETCH_INST()                        @ load rINST from rPC
9867    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9868    GOTO_OPCODE(ip)                     @ jump to next instruction
9869
9870/*
9871 * Invalid array index.
9872 */
9873common_errArrayIndex:
9874    EXPORT_PC()
9875    ldr     r0, strArrayIndexException
9876    mov     r1, #0
9877    bl      dvmThrowException
9878    b       common_exceptionThrown
9879
9880/*
9881 * Invalid array value.
9882 */
9883common_errArrayStore:
9884    EXPORT_PC()
9885    ldr     r0, strArrayStoreException
9886    mov     r1, #0
9887    bl      dvmThrowException
9888    b       common_exceptionThrown
9889
9890/*
9891 * Integer divide or mod by zero.
9892 */
9893common_errDivideByZero:
9894    EXPORT_PC()
9895    ldr     r0, strArithmeticException
9896    ldr     r1, strDivideByZero
9897    bl      dvmThrowException
9898    b       common_exceptionThrown
9899
9900/*
9901 * Attempt to allocate an array with a negative size.
9902 */
9903common_errNegativeArraySize:
9904    EXPORT_PC()
9905    ldr     r0, strNegativeArraySizeException
9906    mov     r1, #0
9907    bl      dvmThrowException
9908    b       common_exceptionThrown
9909
9910/*
9911 * Invocation of a non-existent method.
9912 */
9913common_errNoSuchMethod:
9914    EXPORT_PC()
9915    ldr     r0, strNoSuchMethodError
9916    mov     r1, #0
9917    bl      dvmThrowException
9918    b       common_exceptionThrown
9919
9920/*
9921 * We encountered a null object when we weren't expecting one.  We
9922 * export the PC, throw a NullPointerException, and goto the exception
9923 * processing code.
9924 */
9925common_errNullObject:
9926    EXPORT_PC()
9927    ldr     r0, strNullPointerException
9928    mov     r1, #0
9929    bl      dvmThrowException
9930    b       common_exceptionThrown
9931
9932/*
9933 * For debugging, cause an immediate fault.  The source address will
9934 * be in lr (use a bl instruction to jump here).
9935 */
9936common_abort:
9937    ldr     pc, .LdeadFood
9938.LdeadFood:
9939    .word   0xdeadf00d
9940
9941/*
9942 * Spit out a "we were here", preserving all registers.  (The attempt
9943 * to save ip won't work, but we need to save an even number of
9944 * registers for EABI 64-bit stack alignment.)
9945 */
9946    .macro  SQUEAK num
9947common_squeak\num:
9948    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9949    ldr     r0, strSqueak
9950    mov     r1, #\num
9951    bl      printf
9952    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9953    bx      lr
9954    .endm
9955
9956    SQUEAK  0
9957    SQUEAK  1
9958    SQUEAK  2
9959    SQUEAK  3
9960    SQUEAK  4
9961    SQUEAK  5
9962
9963/*
9964 * Spit out the number in r0, preserving registers.
9965 */
9966common_printNum:
9967    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9968    mov     r1, r0
9969    ldr     r0, strSqueak
9970    bl      printf
9971    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9972    bx      lr
9973
9974/*
9975 * Print a newline, preserving registers.
9976 */
9977common_printNewline:
9978    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9979    ldr     r0, strNewline
9980    bl      printf
9981    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9982    bx      lr
9983
9984    /*
9985     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
9986     */
9987common_printHex:
9988    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
9989    mov     r1, r0
9990    ldr     r0, strPrintHex
9991    bl      printf
9992    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
9993    bx      lr
9994
9995/*
9996 * Print the 64-bit quantity in r0-r1, preserving registers.
9997 */
9998common_printLong:
9999    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10000    mov     r3, r1
10001    mov     r2, r0
10002    ldr     r0, strPrintLong
10003    bl      printf
10004    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10005    bx      lr
10006
10007/*
10008 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10009 */
10010common_printMethod:
10011    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10012    bl      dvmMterpPrintMethod
10013    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10014    bx      lr
10015
10016/*
10017 * Call a C helper function that dumps regs and possibly some
10018 * additional info.  Requires the C function to be compiled in.
10019 */
10020    .if     0
10021common_dumpRegs:
10022    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10023    bl      dvmMterpDumpArmRegs
10024    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10025    bx      lr
10026    .endif
10027
10028#if 0
10029/*
10030 * Experiment on VFP mode.
10031 *
10032 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10033 *
10034 * Updates the bits specified by "mask", setting them to the values in "val".
10035 */
10036setFPSCR:
10037    and     r0, r0, r1                  @ make sure no stray bits are set
10038    fmrx    r2, fpscr                   @ get VFP reg
10039    mvn     r1, r1                      @ bit-invert mask
10040    and     r2, r2, r1                  @ clear masked bits
10041    orr     r2, r2, r0                  @ set specified bits
10042    fmxr    fpscr, r2                   @ set VFP reg
10043    mov     r0, r2                      @ return new value
10044    bx      lr
10045
10046    .align  2
10047    .global dvmConfigureFP
10048    .type   dvmConfigureFP, %function
10049dvmConfigureFP:
10050    stmfd   sp!, {ip, lr}
10051    /* 0x03000000 sets DN/FZ */
10052    /* 0x00009f00 clears the six exception enable flags */
10053    bl      common_squeak0
10054    mov     r0, #0x03000000             @ r0<- 0x03000000
10055    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10056    bl      setFPSCR
10057    ldmfd   sp!, {ip, pc}
10058#endif
10059
10060
10061/*
10062 * String references, must be close to the code that uses them.
10063 */
10064    .align  2
10065strArithmeticException:
10066    .word   .LstrArithmeticException
10067strArrayIndexException:
10068    .word   .LstrArrayIndexException
10069strArrayStoreException:
10070    .word   .LstrArrayStoreException
10071strDivideByZero:
10072    .word   .LstrDivideByZero
10073strNegativeArraySizeException:
10074    .word   .LstrNegativeArraySizeException
10075strNoSuchMethodError:
10076    .word   .LstrNoSuchMethodError
10077strNullPointerException:
10078    .word   .LstrNullPointerException
10079
10080strLogTag:
10081    .word   .LstrLogTag
10082strExceptionNotCaughtLocally:
10083    .word   .LstrExceptionNotCaughtLocally
10084
10085strNewline:
10086    .word   .LstrNewline
10087strSqueak:
10088    .word   .LstrSqueak
10089strPrintHex:
10090    .word   .LstrPrintHex
10091strPrintLong:
10092    .word   .LstrPrintLong
10093
10094/*
10095 * Zero-terminated ASCII string data.
10096 *
10097 * On ARM we have two choices: do like gcc does, and LDR from a .word
10098 * with the address, or use an ADR pseudo-op to get the address
10099 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10100 * PC-relative addressing mode and hence has a limited range, which
10101 * makes it not work well with mergeable string sections.
10102 */
10103    .section .rodata.str1.4,"aMS",%progbits,1
10104
10105.LstrBadEntryPoint:
10106    .asciz  "Bad entry point %d\n"
10107.LstrArithmeticException:
10108    .asciz  "Ljava/lang/ArithmeticException;"
10109.LstrArrayIndexException:
10110    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10111.LstrArrayStoreException:
10112    .asciz  "Ljava/lang/ArrayStoreException;"
10113.LstrClassCastException:
10114    .asciz  "Ljava/lang/ClassCastException;"
10115.LstrDivideByZero:
10116    .asciz  "divide by zero"
10117.LstrFilledNewArrayNotImpl:
10118    .asciz  "filled-new-array only implemented for objects and 'int'"
10119.LstrInternalError:
10120    .asciz  "Ljava/lang/InternalError;"
10121.LstrInstantiationError:
10122    .asciz  "Ljava/lang/InstantiationError;"
10123.LstrNegativeArraySizeException:
10124    .asciz  "Ljava/lang/NegativeArraySizeException;"
10125.LstrNoSuchMethodError:
10126    .asciz  "Ljava/lang/NoSuchMethodError;"
10127.LstrNullPointerException:
10128    .asciz  "Ljava/lang/NullPointerException;"
10129
10130.LstrLogTag:
10131    .asciz  "mterp"
10132.LstrExceptionNotCaughtLocally:
10133    .asciz  "Exception %s from %s:%d not caught locally\n"
10134
10135.LstrNewline:
10136    .asciz  "\n"
10137.LstrSqueak:
10138    .asciz  "<%d>"
10139.LstrPrintHex:
10140    .asciz  "<0x%x>"
10141.LstrPrintLong:
10142    .asciz  "<%lld>"
10143
10144
10145